Takže už ste zvládli premenné aj funkcie, je čas vstúpiť do temných bažín, ktoré v Scheme predstavujú zoznamy (angl. list).
Prv než začneme zoznamy rozoberať hlbšie je potrebné, aby ste pochopili rozdiel medzi atomickými hodnotami a zoznamami.
Z atomickými hodnotami sme sa už stretli keď sme v predchádzajúcej lekcii inicializovali premenné. Atomická hodnota je jednoducho hodnota. V nasledujúcom príklade si ukážeme, ako premennej „x
“ priradíme hodnotu 8.
(let* ( (x 8) ) x)
(Výraz x
sme umiestnili na koniec len preto, aby sa vypísala hodnota priradená premennej x
. Pri bežnom písaní skriptov to nie je nutné robiť takto. Všimnite si, že let*
pracuje podobne ako funkcia: vracia hodnotu posledného výroku.)
Premenná môže odkazovať nielen na jednoduchú hodnotu, ale aj na zoznam hodnôt. Definovanej premennej x
priradíme hodnoty 1, 3, 5 týmto spôsobom:
(let* ( (x '(1 3 5))) x)
Skúste napísať oba výroky do konzoly Script-Fu a sledujte reakcie. Po zadaní prvého výroku dostanete jednoduchý výsledok:
8
Avšak po napísaní druhého výroku dostanete nasledujúci výsledok:
(1 3 5)
Ak dostanete odpoveď s hodnotou 8, znamená to, že premenná x
obsahuje atomickú hodnotu 8. Odpoveď s výsledkom (1 3 5)
však hovorí, že x
neobsahuje iba jednu hodnotu, ale zoznam hodnôt. Všimnite si, že v deklarácii, vo výroku zoznamu, ani vo vypísanom výsledku nie sú čiarky.
Syntax definovania zoznamu je nasledovná:
'(a b c)
kde a
, b
a c
sú literály. Apostrof ('
) naznačuje, že to, čo nasleduje v zátvorkách, je zoznam hodnôt literálov, teda nie funkcia alebo výraz.
Prázdny zoznam môže byť definovaný takto:
'()
alebo jednoducho:
()
Zoznamy môžu obsahovať atomické hodnoty ako aj iné zoznamy:
(let* ( (x '("GIMP" (1 2 3) ("je" ("super" () ) ) ) ) ) x )
Všimnite si, že ak chcete definovať vnútorný zoznam, za prvým apostrofom už nie je ďalší apostrof nutný. Kľudne výrok skopírujte do konzoly Script-Fu a pozorujte výsledok.
Môžete vidieť, že vrátený výsledok nie je zoznam jednoduchých, atomických hodnôt ale skôr zoznam pozostávajúci z literálu ("GIMP")
, zoznamu (1 2 3)
atď.
Zoznamy si môžeme predstaviť ako o útvary zložené z „hlavičky (head)“ a „chvosta (tail)“. Hlava predstavuje prvý prvok zoznamu, chvost zvyšok zoznamu. Prečo je to dôležité uvidíte neskôr, keď si ukážeme ako prvky do zoznamu pridávať a ako ich vyberať.
Jedna z funkcií, s ktorou sa bude stretávať najčastejšie, je funkcia cons. Táto funkcia vezme hodnotu a vloží ju k jej druhému argumentu, k zoznamu. V predchádzajúcej časti som navrhol predstavu zoznamu ako útvaru zloženého z prvku (hlavička) a zvyšku zoznamu (chvost). Presne takto funkcia cons pracuje - pridáva element k hlavičke zoznamu. Takto môžete vytvoriť nasledujúci zoznam:
(cons 1 '(2 3 4) )
Výsledkom je zoznam (1 2 3 4)
.
Vytvoriť môžete aj zoznam obsahujúci iba jeden element:
(cons 1 () )
Namiesto ľubovoľného literálu môžete použiť už deklarované premenné.
Funkcia list
sa používa na definovanie zoznamu zloženého z literálov alebo už deklarovaných premenných.
(list 5 4 3 a b c)
Tak sa vytvorí a vráti zoznam obsahujúci hodnoty priradené k premenným a
, b
a c
. Napríklad:
(let* ( (a 1) (b 2) (c 3) ) (list 5 4 3 a b c) )
Tento kód vytvorí zoznam (5 4 3 1 2 3)
.
K hodnotám v zozname pristupujete pomocou funkcií car
a cdr
. Kým prvá z nich vráti prvý prvok v zozname, druhá funkcia vráti ostatok zoznamu. Tieto funkcie zoznam rozdelia podľa pravidla hlavička::chvost, ako som spomínal vyššie.
Funkcia car
vracia prvý prvok zoznamu (hlavička zoznamu). Zoznam musí byť nenulový. Takže nasledujúci zápis vráti prvý prvok zoznamu:
(car '("prvý" 2 "tretí"))
čo znamená:
"prvý"
Funkcia cdr
vráti všetko, čo nasleduje po prvom prvku v zozname (chvost zoznamu). Ak je na prvom mieste iba jeden prvok, funkcia vráti prázdny zoznam.
(cdr '("prvý" 2 "tretí"))
vráti:
(2 "tretí")
kým nasledujúci:
(cdr '("jeden jediný"))
vráti:
()
Výborne! Teraz už vieme, ako získať prvý a posledný prvok zoznamu. Ale ako sa dostať k tým ostatným, t. j. k druhému, tretiemu atď.? Vybrať si môžete z niekoľkých príjemných funkcií, napr. hlavička hlavičky chvosta zoznamu (caadr
), chvost chvosta zoznamu (cddr
), atď.
Základná konvencia pomenovania takýchto funkcií je jednoduchá: písmeno a a d predstavujú hlavičky a chvosty zoznamov, takže
(car (cdr (car x) ) )
je možné zapísať aj ako:
(cadar x)
Aby ste si funkcie pre prístup k zoznamom precvičili, napíšte nasledujúce (ak však používate konzolu, všetko musí byť na jednom riadku); vyskúšajte rôzne obmeny car
a cdr
na prístup k rôznym prvkom zoznamu:
(let* ( (x '( (1 2 (3 4 5) 6) 7 8 (9 10) ) ) ) ; sem napíšte kódy car/cdr )
Zo zoznamu sa pokúste získať číslo 3 použitím iba dvoch volaní funkcií. Ak to dokážete, možno ste na dobrej ceste stať sa majstrom Script-Fu.
Poznámka | |
---|---|
V Scheme sa bodkočiarkou ( |