Neprogramátor/Nekonečná podstatná jména: seznamy
Seznam je několik kouzelných slov dohromady, jako třeba čarodějův nákupní seznam, který se vytvoří kouzelnou větou začínající kouzelným slovesem list
:
(list "ředkvičky" "rum" "rýže" "tofu" "minerálka")
Výsledek vykonání takové kouzelné věty je kouzelné podstatné jméno
'("ředkvičky" "rum" "rýže" "tofu" "minerálka")
které vypadá tak trochu jako kouzelná věta se špatnou gramatikou (protože ji chybí sloveso), před kterou je navíc apostrof '
.
Seznam je tedy kouzelné podstatné jméno, které začíná apostrofem a závorkou '(
, pak následuje výčet kouzelných podstatných jmen, která jsou součástí seznamu, a končí zase (jako kouzelné věty) závorkou )
.
První položka a zbytek seznamu
editovatSeznam seskládá z kouzelného podstatného jména, které je v seznamu první, a z ostatních kouzelných podstatných jmen, která vlastně tvoří další seznam.
První položku seznamu lze získat kouzelnou větou začínající kouzelným slovesem first
:
(first '("ředkvičky" "rum" "rýže" "tofu" "minerálka"))
"ředkvičky"
a zbytek seznamu kouzelnou větou začínající kouzelným slovesem rest
:
(rest '("ředkvičky" "rum" "rýže" "tofu" "minerálka"))
'("rum" "rýže" "tofu" "minerálka")
Seznam je kouzelné podstatné jméno, takže je v pořádku, že je v kouzelné větě až po kouzelném slovesu.
Čarodějové ale mohou vytvářet mocné kouzelné věty jejich vnořováním. Jak v předchozích příkladech použít kouzelnou větu začínající kouzelným slovesem list
?
(first (list "ředkvičky" "rum" "rýže" "tofu" "minerálka"))
(rest (list "ředkvičky" "rum" "rýže" "tofu" "minerálka"))
"ředkvičky" '("rum" "rýže" "tofu" "minerálka")
Použít '(list ...
je špatně, protože '(
je začátek seznamu, tedy kouzelného podstatného jména.
'(list "ředkvičky" "rum" "rýže" "tofu" "minerálka")
'(list "ředkvičky" "rum" "rýže" "tofu" "minerálka")
Kouzelná hůlka si pak myslí, že list
je první kouzelné podstatné jméno seznamu a "ředkvičky"
až druhé.
Ať je seznam rovnou kouzelné podstatné jméno '(...
nebo výsledek vykonání kouzelné věty začínající kouzelným slovesem list
, v předchozím příkladu je dvakrát.
Jak použít define
pro zabránění opakování?
(define seznam (list "ředkvičky" "rum" "rýže" "tofu" "minerálka"))
; nebo (define seznam '("ředkvičky" "rum" "rýže" "tofu" "minerálka"))
(first seznam)
(rest seznam)
"ředkvičky" '("rum" "rýže" "tofu" "minerálka")
Funguje i let
?
Ne úplně!
(let ((seznam (list "ředkvičky" "rum" "rýže" "tofu" "minerálka")))
(first seznam)
(rest seznam))
'("rum" "rýže" "tofu" "minerálka")
Je to kvůli tomu, že výsledek vykonání mocné kouzelné věty začínající slovesem let
je jen jeden. Nejdříve se vykoná kouzelná věta začínající kouzelným slovesem list
a výsledek je dostupný jako kouzelné podstatné jméno seznam
. Pak se vykoná kouzelná věta (first seznam)
. Nakonec se vykoná kouzelná věta (rest seznam)
a protože je poslední, použije se jako výsledek vykonání mocné kouzelné věty začínající kouzelným slovesem let
.
Seznam, který nemá žádnou položku, je prázdný seznam. Vytvoří se kouzelnou větou začínající kouzelným slovesem list
, která ale nemá žádná další kouzelná podstatná jména:
(list)
'()
Nebo se prázdný seznam může napsat rovnou jako kouzelné podstatné jméno:
'()
'()
Jaká je první položka seznamu '("ředkvičky" "rum")
(který má dvě položky)?
(first '("ředkvičky" "rum"))
"ředkvičky"
Jaký je zbytek seznamu '("ředkvičky" "rum")
(který má dvě položky)?
(rest '("ředkvičky" "rum"))
'("rum")
I když zbytek seznamu obsahuje jenom jednu položku, je to pořád seznam!
Jaká je první položka seznamu '("rum")
(který má jednu položku)?
(first '("rum"))
"rum"
Jaký je zbytek seznamu '("rum")
(který má jednu položku)?
(rest '("rum"))
'()
Jaká je první položka prázdného seznamu '()
?
(first '())
Chyba! Prázdný seznam nemá první položku!
. . first: contract violation expected: (and/c list? (not/c empty?)) given: '()
Jaký je zbytek prázdného seznamu '()
?
(rest '())
Chyba! Prázdný seznam nemá zbytek!
. . rest: contract violation expected: (and/c list? (not/c empty?)) given: '()
Jestli je seznam prázdný se dá zjistit kouzelnou větou začínající kouzelným slovesem null?
:
(null? (list))
(null? '())
(null? (list "ředkvičky" "rum" "rýže" "tofu" "minerálka"))
(null? '("ředkvičky" "rum" "rýže" "tofu" "minerálka"))
#t #t #f #f
Je zbytek seznamu '("ředkvičky" "rum")
, který má dvě položky, prázdný seznam?
(null? (rest '("ředkvičky" "rum")))
Není!
#f
Je zbytek seznamu '("rum")
, který má jednu položku, prázdný seznam?
(null? (rest '("rum")))
Je!
#t
Délka seznamu
editovatČarodějové velmi často pracují se seznamy nebo s podobnými kouzelnými podstatnými jmény, kterých je více v jednom. Klasický (kouzelnický) učebnicový příklad práce se seznamem je zjištění délky seznamu.
(délka-seznamu '("ředkvičky" "rum" "rýže" "tofu" "minerálka"))
Když ale čaroděj poprosí kouzelnou hůlku, aby vykonala takovou kouzelnou větu, místo výsledku 5
kouzelná hůlka odpoví:
. délka-seznamu: unbound identifier in: délka-seznamu
Kouzelnou hůlku je totiž potřeba naučit nové kouzelné sloveso délka-seznamu
. Čaroděj ví, co od kouzelné věty začínající kouzelným slovesem délka-seznamu
očekává:
(= 5 (délka-seznamu '("ředkvičky" "rum" "rýže" "tofu" "minerálka")))
#t
a taky že
(délka-seznamu '())
0
(délka-seznamu '("ředkvičky"))
1
(délka-seznamu '("ředkvičky" "rum"))
2
Velkou částí práce čaroděje je hledat v problémech vzorce (stereotypy, dá se říci). Zkušenější čaroděj v problému délky seznamu jeden takový vzorec rozpozná na první dobrou: Nejkratší možný seznam, prázdný seznam, tedy '()
, má délku 0
; vždy po přidání nějaké položky do takového seznamu se délka seznamu zvýší o 1
.
Čaroděje takové rekurzivní přemýšlení přivede k nápadu, jak kouzelnou hůlku kouzelné sloveso délka-seznamu
naučit:
(define (délka-seznamu seznam)
(if (null? seznam)
0
(+ 1 (délka-seznamu (rest seznam)))))
Takže když se pak čaroděj kouzelné hůlku zeptá, jak dlouhý je jeho nákupní seznam
(délka-seznamu '("ředkvičky" "rum" "rýže" "tofu" "minerálka"))
kouzelná hůlka už bude vědět a odpoví:
5
Co kouzelná hůlka odpoví na kouzelnou větu (délka-seznamu '("ředkvičky"))
?
1
Co kouzelná hůlka odpoví na kouzelnou větu (délka-seznamu '("ředkvičky" "rum"))
?
2
Co kouzelná hůlka odpoví na kouzelnou větu (délka-seznamu '())
?
0
Délka seznamu je klasický (kouzelnický) učebnicový příklad proto, že kouzelná hůlka kouzelné sloveso pro zjištění délky seznamu samozřejmě zná -- čarodějové jej používají dost často. Kouzelné sloveso pro zjištění délky seznamu je length
.
Jak ověřit, že kouzelné sloveso délka-seznamu
funguje stejně jako kouzelné sloveso length
?
Nejde to zjistit na sto procent, ale čaroděj si může být celkem jistý, když porovná několik seznamů:
(and
(= (length '("ředkvičky" "rum" "rýže" "tofu" "minerálka"))
(délka-seznamu '("ředkvičky" "rum" "rýže" "tofu" "minerálka")))
(= (length '("ředkvičky" "rum"))
(délka-seznamu '("ředkvičky" "rum")))
(= (length '("ředkvičky"))
(délka-seznamu '("ředkvičky")))
(= (length '())
(délka-seznamu '())))
#t
Kouzelná věta začínající kouzelným slovesem and
je predikát, takže vykonání takové kouzelné věty je pravda #t
nebo nepravda #f
. Pravda #t
je to tehdy, když jsou pravda všechny kouzelné věty, které kouzelná věta začínající kouzelným slovesem and
obsahuje, a nepravda #f
je to tehdy, když některá z kouzelných vět neplatí.
V tomto případě všechny takové kouzelné věty, které jsou součástí mocné kouzelné věty začínající kouzelným slovesem and
, začínají kouzelným slovesem =
. Vykonání kouzelné věty, která začíná kouzelným slovesem =
, je pravda #t
, když jsou všechna kouzelná podstatná jména následující =
stejná čísla.
V kouzelných větách, které začínají kouzelným slovesem =
, jsou dvě další kouzelné věty. První začíná kouzelným slovesem length
a druhá začíná kouzelným slovesem délka-seznamu
.
Obě kouzelné věty začínající kouzelnými slovesy length
a délka-seznamu
, když je kouzelná hůlka vyhodnotí, vrátí kouzelné podstatné jméno, které je číslo. Hodí se tedy jako podstatná jména pro kouzelnou větu začínající kouzelným slovesem =
, která vrátí pravdivostní hodnotu, tedy pravdu #t
nebo nepravdu #f
. Pravdivostní hodnota se zase hodí pro kouzelnou větu začínající kouzelným slovesem and
, která vlastně zkontroluje, že všechny kouzelné věty začínající kouzelným slovesem =
platí. Pokud ano, kouzelná věta začínající kouzelným slovesem and
také platí a po jejím vykonání kouzelná hůlka vrátí #t
.
Procházení seznamu
editovatZjištění délky seznamu čaroděj provedl tak, že pro každou položku seznamu přičetl + 1
. K čemu? K délce prázdného seznamu, která je 0
.
To ale znamená, že poprosil kouzelnou hůlku, aby použila první kouzelné podstatné jméno ze seznamu, pak druhé, třetí, ... až nezbylo žádné. Kouzelná hůlka "procházela" seznam, položku po položce, jedno kouzelné podstatné jméno za druhým.
Použít kouzelné podstatné jméno při počítání délky seznamu znamená, že se sečte jednička 1
s délkou zbytku seznamu. Kouzelné podstatné jméno ze seznamu, ať je jakékoli, se tedy změní na konkrétní číslo 1
.
Stejným způsobem ale může čaroděj naučit kouzelnou hůlku nové kouzelné sloveso, které z nákupního seznamu kouzelných podstatných jmen vytvoří jedno kouzelné podstatné jméno, které je text obsahující položky nákupního seznamu oddělené čárkou. Čaroděj vyjde z kouzelné věty, pomocí které kouzelnou hůlku naučil nové kouzelné sloveso délka-seznamu
:
(define (délka-seznamu seznam)
(if (null? seznam)
0
(+ 1 (délka-seznamu (rest seznam)))))
Nové kouzelné sloveso bude položky-oddělené-čárkou
:
(define (položky-oddělené-čárkou seznam)
(if (null? seznam)
0
(+ 1 (položky-oddělené-čárkou (rest seznam)))))
Pro prázdný seznam ale čaroděj nechce vrátit 0
, ale prázdný text, tedy ""
:
(define (položky-oddělené-čárkou seznam)
(if (null? seznam)
""
(+ 1 (položky-oddělené-čárkou (rest seznam)))))
Stejně tak nemá smysl pro seznam, který prázdný není, používat kouzelnou větu začínající kouzelným slovesem +
. To je kouzelné sloveso pro čísla. Čaroděj ale přemýšlí o kouzelných slovesech pro text! Nakonec si čaroděj vzpomene, že pro spojení textů se skvěle hodí kouzelné sloveso string-append
:
(define (položky-oddělené-čárkou seznam)
(if (null? seznam)
""
(string-append 1 (položky-oddělené-čárkou (rest seznam)))))
Zbývá už je opravit poslední maličkost: 1
není text a kouzelná věta (string-append 1 "")
tak nedává smysl.
Jak opravit definici nového kouzelného slovesa položky-oddělené-čárkou
, aby dávala smysl?
(define (položky-oddělené-čárkou seznam)
(if (null? seznam)
""
(string-append (first seznam)
(položky-oddělené-čárkou (rest seznam)))))
Když čaroděj naučí kouzelnou hůlku nové kouzelné sloveso položky-oddělené-čárkou
, co kouzelná hůlka vypíše po vykonání následující kouzelné věty?
(položky-oddělené-čárkou
'("ředkvičky" "rum" "rýže" "tofu" "minerálka"))
"ředkvičkyrumrýžetofuminerálka"
Je výsledek vykonání kouzelnou hůlkou to, co čaroděj chtěl? Jestli ano, skvělé! Jestli ne, jsou tu ještě dva úkoly:
Jak opravit definici nového kouzelného slovesa položky-oddělené-čárkou
, aby byl výsledek vykonání kouzelné věty
(položky-oddělené-čárkou
'("ředkvičky" "rum" "rýže" "tofu" "minerálka"))
text oddělený čárkou (a mezerou)?
(define (položky-oddělené-čárkou seznam)
(if (null? seznam)
""
(string-append (first seznam)
", "
(položky-oddělené-čárkou (rest seznam)))))
(položky-oddělené-čárkou
'("ředkvičky" "rum" "rýže" "tofu" "minerálka"))
"ředkvičky, rum, rýže, tofu, minerálka, "
Jak opravit definici nového kouzelného slovesa položky-oddělené-čárkou
, aby se čaroděj zbavil čárky a mezery ,
na konci textu?
Nápověda: Je potřeba změnit ukončující podmínku.
Nápověda: V ukončující podmínce je potřeba testovat zbytek seznamu.
(define (položky-oddělené-čárkou seznam)
(if (null? (rest seznam))
(first seznam)
(string-append (first seznam)
", "
(položky-oddělené-čárkou (rest seznam)))))
(položky-oddělené-čárkou
'("ředkvičky" "rum" "rýže" "tofu" "minerálka"))
"ředkvičky, rum, rýže, tofu, minerálka"
Vytváření seznamu
editovatProcházení seznamu používá princip rekurze: ukončující podmínka říká, co odpovídá prázdnému seznamu a rekurzivní krok určuje, jak se vytvoří výsledek z první položky seznamu a výsledku vykonání rekurzivní funkce na zbytek seznamu.
Pro kouzelné sloveso délka-seznamu
vrátí ukončující podmínka 0
a rekurzivní krok přičte + 1
k výsledku vykonání délka-seznamu
na zbytek seznamu:
(délka-seznamu '("ředkvičky" "rum"))
je tak postupně:
(+ 1 (délka-seznamu '("rum")))
(+ 1 (+ 1 (délka-seznamu '())))
(+ 1 (+ 1 0))
(+ 1 1)
2
A
(položky-oddělené-čárkou '("ředkvičky" "rum"))
kouzelná hůlka postupně vyhodnotí jako:
(string-append "ředkvičky" ", " (položky-oddělené-čárkou '("rum")))
(string-append "ředkvičky" ", " "rum")
Jak to, že při použití kouzelné věty začínající kouzelným slovesem položky-oddělené-čárkou
nikde není prázdný seznam '()
?
Aby se čaroděj vyhnul čárce a mezeře na konci textu, ukončující podmínka kouzelného slovesa položky-oddělené-čárkou
zohledňuje zbytek seznamu, nikoli seznam jako takový. Ukončující podmínka se proto aktivuje už při
(null? (rest '("rum")))
#t
a když je zbytek seznamu prázdný, tedy platí ukončující podmínka, vrátí položky-oddělené-čárkou
první položku ze seznamu (first seznam)
, tomto případě "rum"
.
Stejným způsobem, jakým čaroděj naučil kouzelnou hůlku, aby ze seznamu udělala číslo (délku seznamu) nebo text (položky oddělené čárkou), může čaroděj naučit kouzelnou hůlku, aby ze seznamu udělala seznam. Stačí použít to správné kouzelné sloveso v rekurzivním kroku! Místo +
pro délku seznamu (číslo) a string-append
pro položky oddělené čárkou (text) použije čaroděj kouzelné sloveso cons
, které z kouzelného podstatného jména a seznamu udělá seznam:
(let ((seznam '("ředkvičky" "rum" "rýže" "tofu" "minerálka")))
(equal? (cons (first seznam) (rest seznam))
seznam))
#t
Cože? #t
? Kouzelná věta začínající kouzelným slovesem let
říká, že kouzelné podstatné jméno seznam
je to samé, jako nový seznam, který vznikne kouzelnou větu začínající kouzelným slovesem cons
, kde je první kouzelné podstatné jméno první položka seznamu (first seznam)
a druhé kouzelné podstatné jméno zbytek seznamu (rest seznam)
.
Pokud je druhé kouzelné podstatné jméno (tedy třetí kouzelné slovo) kouzelné věty začínající kouzelným slovesem cons
seznam, je výsledek vykonání takové kouzelné věty zase seznam:
(cons "ředkvičky" '())
'("ředkvičky")
Protože je seznam kouzelné podstatné jméno, může čaroděj vytvořit mocnou kouzelnou větu, která obsahuje další kouzelnou větu s kouzelným slovesem cons
:
(cons "rum" (cons "ředkvičky" '()))
'("rum" "ředkvičky")
Když se teď čaroděj trochu zamyslí, zvládne naučit kouzelnou hůlku nové kouzelné sloveso kopíruj
, které vytvoří nový nákupní seznam, úplně stejný jako ten původní:
(kopíruj '("ředkvičky" "rum" "rýže" "tofu" "minerálka"))
'("ředkvičky" "rum" "rýže" "tofu" "minerálka")
Jak by mohla vypadat kouzelná věta (začínající kouzelným slovesem define
), která naučí kouzelnou hůlku nové kouzelné sloveso kopíruj
?
(define (kopíruj seznam)
(if (null? seznam)
'()
(cons (first seznam) (kopíruj (rest seznam)))))
Než půjde čaroděj nakupovat, chtěl by vědět, na kolik jej nákup vyjde. Ceny v kouzelném krámku jsou samozřejmě kouzelné a platí, že čaroděj za položku ze seznamu zaplatí tolik, kolik písmen položka ze seznamu má.
Jak čaroděj naučí kouzelnou hůlku, aby rozuměla kouzelné větě (cena "položky")
?
(define (cena položky)
(string-length položky))
(cena "položky")
7
Čaroděj ví, že správně by měl nové kouzelné věty testovat. Jak by vypadal kompletní dopis pro kouzelnou hůlku, ve které čaroděj kouzelnou hůlku naučí nové kouzelné sloveso (cena "položky")
a kdyby udělal chybu, kouzelná hůlka mu dá vědět?
Nápověda: Možná bude potřeba vzpomenout jednu z předchozích kapitol.
#lang racket
(module+ test (require rackunit))
(define (cena položky)
(string-length položky))
(module+ test
(check-equal? 0 (cena ""))
(check-equal? 9 (cena "ředkvičky"))
(check-equal? 3 (cena "rum")))
A jak čaroděj naučí kouzelnou hůlku, aby mu prozradila ceny všech položek z jeho seznamu? Jak by vypadal úplně celý dopis pro kouzelnou hůlku?
Třeba kouzelným slovesem ceny-položek
:
(define (ceny-položek seznam)
(if (null? seznam)
'()
(cons (cena (first seznam)) (ceny-položek (rest seznam)))))
(ceny-položek '("ředkvičky" "rum" "rýže" "tofu" "minerálka"))
'(9 3 4 4 9)
Celý dopis pro kouzelnou hůlku zatím obsahuje:
#lang racket
(module+ test (require rackunit))
(define (cena položky)
(string-length položky))
(module+ test
(check-equal? 0 (cena ""))
(check-equal? 9 (cena "ředkvičky"))
(check-equal? 3 (cena "rum")))
(define (ceny-položek seznam)
(if (null? seznam)
'()
(cons (cena (first seznam)) (ceny-položek (rest seznam)))))
(module+ test
(check-equal? '() (ceny-položek '()))
(check-equal? '(9 3 4 4 9)
(ceny-položek '("ředkvičky"
"rum"
"rýže"
"tofu"
"minerálka"))))
A nakonec zbývá čaroději zjistit, kolik za svůj nákup zaplatí dohromady.
(define (cena-seznamu seznam)
(if (null? seznam)
0
(+ (cena (first seznam)) (cena-seznamu (rest seznam)))))
(cena-seznamu '("ředkvičky" "rum" "rýže" "tofu" "minerálka"))
29
Úplně celý dopis pro kouzelnou hůlku tedy zní:
#lang racket
(module+ test (require rackunit))
(define (cena položky)
(string-length položky))
(module+ test
(check-equal? 0 (cena ""))
(check-equal? 9 (cena "ředkvičky"))
(check-equal? 3 (cena "rum")))
(define (ceny-položek seznam)
(if (null? seznam)
'()
(cons (cena (first seznam)) (ceny-položek (rest seznam)))))
(module+ test
(check-equal? '() (ceny-položek '()))
(check-equal? '(9 3 4 4 9)
(ceny-položek '("ředkvičky"
"rum"
"rýže"
"tofu"
"minerálka"))))
(define (cena-seznamu seznam)
(if (null? seznam)
0
(+ (cena (first seznam)) (cena-seznamu (rest seznam)))))
(module+ test
(check-equal? 0 (cena-seznamu '()))
(check-equal? (+ 9 3 4 4 9)
(cena-seznamu '("ředkvičky"
"rum"
"rýže"
"tofu"
"minerálka"))))
Kouzelnické triky pro vytváření seznamu
editovatČarodějové používají nespočet triků a při vytváření seznamu by bylo neodpustitelné nezmínit trik s akumulátorem. Trik spočívá v tom, že se malinko upraví ukončující podmínka a rekurzivní krok.
V rekurzivním kroku čaroděj místo spojování první položky seznamu a výsledku vykonání rekurzivní funkce na zbytek seznamu použije kouzelnou větu začínajícím rekurzivním kouzelným slovesem, ve které vedle starého seznamu použije také nový seznam, který bude fungovat jako akumulátor.
V ukončující podmínce, když je starý seznam prázdný, řekne čaroděj kouzelné hůlce, aby vrátila akumulátor, tedy nový seznam.
Je to jakoby kouzelná věta začínající rekurzivním kouzelným slovesem "přelévala" starý seznam do toho nového.
Výsledek vyhodnocení kouzelné věty
(pozpátku '("ředkvičky" "rum" "rýže" "tofu" "minerálka") '())
je potom
'("minerálka" "tofu" "rýže" "rum" "ředkvičky")
Je vidět, že kouzelná věta začínající kouzelným slovesem pozpátku
má dvě kouzelná podstatná jména: první je starý
seznam a druhé je nový
seznam. Nový seznam funguje jako akumulátor.
Čaroděj naučil kouzelnou hůlku nové kouzelné sloveso pozpátku
pomocí kouzelné věty
(define (pozpátku starý nový) ; nový je akumulátor
(if (null? starý)
nový
(pozpátku (rest starý) (cons (first starý) nový))))
Obrácení seznamu je zase klasický (kouzelnický) učebnicový příklad. Čarodějové kouzelnou hůlku nemusí kouzelné sloveso pozpátku
učit, protože kouzelná hůlka už zná reverse
.
Jak ověřit, že kouzelné sloveso pozpátku
funguje stejně jako kouzelné sloveso reverse
?
Nejde to zjistit na sto procent, ale čaroděj si může být celkem jistý, když porovná několik seznamů:
(and
(equal? (reverse '("ředkvičky" "rum" "rýže" "tofu" "minerálka"))
(pozpátku '("ředkvičky" "rum" "rýže" "tofu" "minerálka") '()))
(equal? (pozpátku '("ředkvičky" "rum" "rýže" "tofu" "minerálka") '())
'("minerálka" "tofu" "rýže" "rum" "ředkvičky"))
(equal? (reverse '("ředkvičky" "rum"))
(pozpátku '("ředkvičky" "rum") '()))
(equal? (pozpátku '("ředkvičky" "rum") '())
'("rum" "ředkvičky"))
(equal? (reverse '("ředkvičky"))
(pozpátku '("ředkvičky") '()))
(equal? (pozpátku '("ředkvičky") '())
'("ředkvičky"))
(equal? (reverse '())
(pozpátku '() '()))
(equal? (pozpátku '() '())
'()))
#t
Druhý trik, který stojí za zmínku, zjednoduší používání kouzelného slovesa pozpátku
-- čaroděj naučí kouzelnou hůlku nové kouzelné sloveso jen-pozpátku
, aby mohli čarodějové myslet jen na jeden seznam
. Pointa triku je ve skládání mocných kouzelných vět.
(define (jen-pozpátku seznam)
(define (pozpátku starý nový) ; nový je akumulátor
(if (null? starý)
nový
(pozpátku (rest starý) (cons (first starý) nový))))
(pozpátku seznam '()))
(jen-pozpátku '("ředkvičky" "rum" "rýže" "tofu" "minerálka"))
'("minerálka" "tofu" "rýže" "rum" "ředkvičky")
Jak by mohl vypadat kompletní dopis pro kouzelnou hůlku, v četně testů, ve kterém je definice jen-pozpátku
?
#lang racket
(module+ test (require rackunit))
(define (jen-pozpátku seznam)
(define (pozpátku starý nový) ; nový je akumulátor
(if (null? starý)
nový
(pozpátku (rest starý) (cons (first starý) nový))))
(pozpátku seznam '()))
(module+ test
(check-equal?
(jen-pozpátku '("ředkvičky" "rum" "rýže" "tofu" "minerálka"))
'("minerálka" "tofu" "rýže" "rum" "ředkvičky"))
(check-equal?
(jen-pozpátku '("ředkvičky" "rum"))
'("rum" "ředkvičky"))
(check-equal?
(jen-pozpátku '("ředkvičky"))
'("ředkvičky"))
(check-equal?
(jen-pozpátku '())
'()))
Shrnutí seznamů
editovatSeznam je kouzelné podstatné jméno, které obsahuje další kouzelná podstatná jména.
Vypadá trochu jako kouzelná věta, ale nemá sloveso a začíná apostrofem a závorkou '(
, za kterými následují kouzelná podstatná jména oddělená mezerami a nakonec zase závorka )
.
Čarodějové rádi používají kouzelná podstatná jména spolu s rekurzí, protože jim pomáhají vyjádřit problémy, které se opakují.
◄ Neprogramátor/Kouzelné sloveso je kouzelné sloveso: rekurze | Nekonečná podstatná jména: seznamy |