Předcházející |  | Další

### 11.3. Seznamy, seznamy a zase seznamy

Již umíte pracovat s proměnnými a funkcemi, je na čase vydat se za tajemstvím seznamů (anglicky lists, které tvoří důležitou součást Scheme.

#### 11.3.1. Definování seznamu

Dříve, než si o seznamech povíme více, musíte pochopit rozdíl mezi atomickými hodnotami a seznamy.

Atomické hodnoty jsme viděli již při inicializaci proměnných v předchozí lekci. Atomická hodnota je jedna jediná hodnota. Následujícím výrokem přiřadíme proměnné `x` (atomickou) hodnotu 8:

            (let* ( (x 8) ) x)

(Výraz `x` je na konci uveden jen proto, aby hodnotu proměnné `x` z ilustrativních důvodů vypsal, při běžném skriptování není nutný. Všimněte si, že `let*` pracuje podobně jako funkce – vrací hodnotu posledního výroku.)

Proměnná může také odkazovat na seznam hodnot, ne na hodnotu jedinou. Přiřadit proměnné `x` seznam hodnot 1, 3, 5 lze takto:

            (let* ( (x '(1 3 5))) x)

Zkuste oba výroky ve Script-Fu konzoli a sledujte reakci. První výrok vrátí výsledek:

            8

Druhý výrok však vrátí následující výsledek:

            (1 3 5)

Odpoveď 8 značí, že proměnná `x` obsahuje atomickou hodnotu 8. Odpověď (1 3 5) však říká, že proměnná `x` neobsahuje jednu hodnotu, nýbrž seznam hodnot. Všimněte si, že v deklaraci, přiřazení seznamu, ani ve vypsaném výsledku nejsou žádné čárky.

Syntaxe definice seznamu je následující:

            '(a b c)

kde `a`, `b` a `c` jsou literály. Apostrof (') značí, že v následujících závorkách je seznam literálů, nikoliv funkce či výraz.

Prázdný seznam lze definovat následujícím způsobem:

            '()

nebo jednodušeji:

            ()

Seznamy mohou obsahovat atomické hodnoty i další seznamy:

            (let*
               (
                   (x
                      '("The Gimp" (1 2 3) ("is" ("great" () ) ) )
                   )
               )

               x
            )

Všimněte si, že za prvním apostrofem již není, pro vnitřní seznamy, apostrofy používat. Přepiště výrok do jedné řádky, vložte do Script-Fu konzole, vyzkoušejte a prohlédněte si výsledek.

Vrácený výsledek není seznam jednotlivých atomických hodnot, ale obsahuje literál `("The Gimp")`, seznam `(1 2 3)` atd.

#### 11.3.2. Kterak přemýšlet o seznamech

O seznamech je často užitečné přemýšlet jako o útvarech složených z hlavičky a ocásku (anglicky head a tail). Hlavička je první položka seznamu, zbývající položky tvoří ocásek. Bude to užitečné, až budeme mluvit o spojování seznamů a přístupu k jednotlivým prvkům seznamu.

#### 11.3.3. Vytváření seznamů spojováním (funkce cons)

Jedna z funkcí, se kterými se budete setkávat nejčastěji, je funkce `cons` (z anglického concatenation). Tato funkce vezme hodnotu a připojí ji před svůj druhý argument, seznam. V předchozím odstavci jsme navrhli představu seznamu jako útvaru složeného z hlavičky a ocásku. Funkce `cons` přidává seznamu nový prvek na místo jeho hlavičky. Například takto:

            (cons 1 '(2 3 4) )

Výsledkem je seznam `(1 2 3 4)`.

Lze takto vytvořit i seznam s jedním prvkem:

            (cons 1 () )

Místo kteréhokoliv literálu můžete samozřejmě použít dříve deklarovanou proměnnou.

#### 11.3.4. Definice seznamu pomocí funkce list

Pro definici seznamu složeného z literálů a dříve deklarovaných proměnných můžete použít funkci `list`:

            (list 5 4 3 a b c)

Tak se vytvoří a vrátí seznam obsahující hodnoty proměnných `a`, `b` a `c`. Například:

            (let*  (
                      (a 1)
                      (b 2)
                      (c 3)
                   )
                   (list 5 4 3 a b c)
            )

Tento kód vytvoří seznam `(5 4 3 1 2 3)`.

#### 11.3.5. Přístupování k hodnotám v seznamu

K přistupování k hodnotám v seznamu slouží funkce `car` a `cdr`. První vrací první prvek v seznamu (hlavičku), druhá vrací zbytek seznamu (ocásek).

#### 11.3.6. Funkce `car`

Funkce `car` vrací první prvek seznamu (hlavičku). Seznam musí být nenulový. Například:

            (car '("prvni" 2 "treti"))

vrátí:

            "prvni"

#### 11.3.7. Funkce `cdr`

Funkce `cdr` vrací celý seznam kromě jeho prvního prvku, tedy ocásek seznamu. Pokud seznam obsahuje jediný prvek, vrací prázdný seznam.

            (cdr '("prvni" 2 "treti"))

vrací:

            (2 "treti")

zatímco následující:

            (cdr '("one and only"))

vrací:

            ()

#### 11.3.8. Přístup k dalším prvkům v seznamu

Výborně, již umíme získat první prvek ze seznamu i zbytek seznamu. Jak ale přistupovat ke druhému, třetímu nebo jinému prvku seznamu? K tomuto účelu existuje řada praktických funkcí, např. hlavička hlavičky ocásku seznamu (`caadr`), ocásek ocásku seznamu (`cddr`) atd.

Konvence pro pojemnovávání takových to funkcí je velmi jednoduchá. Písmena `a` představují hlavičky, písmena `d` představují ocásky. Například:

            (car (cdr (car x) ) )

lze jednodušeji zapsat jako:

            (cadar x)

Úplný seznam funkcí pro práci se seznamy ve Script-Fu naleznete v příloze.

Abyste si funkce pro přístup k prvkům seznamu procvičili, zadejte následující (ovšem, pokud používáte konzoli, na jednom řádku) a zkoušejte si různé kombinace `car` a `cdr` pro přístup k různým prvkům seznamu:

            (let* (
                     (x  '( (1 2 (3 4 5) 6)  7  8  (9 10) )
                     )
                  )
                  ; sem zapište svou car/cdr funkci
            )

Pokuste se získat číslo tři pouze dvěma voláními funkce. Pokud se vám to podaří, možná se z vás stane Mistr Script-Fu!

| Poznámka
Ve Scheme uvádí středník (";") komentář. Středník, a vše co za ním následuje, až do konce řádky, interpretr ignoruje. Do komentářů si můžete psát různé vysvětlující poznámky k funkci skriptu.

Předcházející | Nahoru | Další
| Domů |