3.3. Listor, listor och åter listor
| 3. En Script-Fu-handledning |

### 3.3. Listor, listor och åter listor

Vi har tränat dig i variabler och funktioner, och går nu in i de dunkla kärr som är Schemes listor.

#### 3.3.1. Definiera en lista

Innan vi pratar mer om listor är det nödvändigt att du vet skillnaden mellan atomära värden och listor.

Du har redan sett atomära värden när vi initierade variabler i föregående lektion. Ett atomärt värde är ett ensamt värde. Så vi kan exempelvis tilldela variabeln ”`x`” det ensamma värdet 8 i följande sats:

    (let* ( (x 8) ) x)

(Vi la till uttrycket `x` i slutet för att skriva ut värdet som `x` tilldelats — vanligen kommer du inte behöva göra detta. Se hur `let*` beter sig precis som en funktion: Värdet på den sista satsen är värdet som returneras.)

En variabel kan också hänvisa till en lista med värden, snarare än ett ensamt värde. För att tilldela variabeln `x` värdelistan 1, 3, 5, skulle vi skriva:

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

Försök skriva båda satserna i Script-Fu-konsolen och se hur den svarar. När du matar in den första satsen svarar den helt enkelt med resultatet:

    8

När du matar in den andra satsen svarar den dock med följande resultat:

    (1 3 5)

När den svarar med värdet 8 informerar den dig om att `x` innehåller det atomära värdet 8. När den svarar med `(1 3 5)` informerar den dig dock om att `x` inte innehåller ett ensamt värde, utan en lista med värden. Notera att det inte finns några kommatecken i vår deklaration eller tilldelning av listan, och inte heller i det utskrivna resultatet.

Syntax för att definiera en lista är:

    '(a b c)

där `a`, `b`, och `c` är litteraler. Vi använder apostrofen (`'`) för att indikera att det som följer i parenteserna är en lista med faktiska värden, snarare än en funktion eller ett uttryck.

En tom lista kan definieras så här:

    '()

eller helt enkelt:

    ()

Listor kan innehålla atomära värden, såväl som andra listor:

    (let*
       (
            (x
               '("GIMP" (1 2 3) ("är" ("bäst" () ) ) )
            )
        )
        x
    )

Notera att efter den första apostrofen så behöver du inte längre använda en apostrof när du definierar de inre listorna. Varsågod att kopiera satsen till Script-Fu-konsolen och se vad den returnerar.

Du bör notera att resultatet som returneras inte är en lista med enstaka, atomära värden. Snarare är det en lista med en litteral `("GIMP")`, listan `(1 2 3)` och så vidare.

#### 3.3.2. Hur du ska tänka om listor

Det är användbart att tänka på listor som bestående av ett ”huvud” och en ”svans”. Huvudet är listans första element, svansen är resten av listan. Du kommer att se varför detta är viktigt när vi diskuterar hur vi lägger till i listor samt hur vi kommer åt element i listan.

#### 3.3.3. Skapa listor genom konkatenering (funktionen cons)

En av de vanligare funktionerna du kommer stöta på är funktionen cons. Den tar ett värde och slår ihop det med sitt andra argument, en lista. Från föregående avsnitt föreslog jag att du tänker på en lista som bestående av ett element (huvudet) och resten av listan (svansen). Detta är exakt hur cons fungerar — det lägger till ett element i huvudet på en lista. Därmed skulle du kunna skapa en lista som följer:

    (cons 1 '(2 3 4) )

Resultatet är listan `(1 2 3 4)`.

Du skulle också kunna skapa en lista med ett element:

    (cons 1 () )

Du kan använda tidigare deklarerade variabler i stället för alla litteraler, som du skulle kunna förvänta dig.

#### 3.3.4. Definiera en lista med funktionen `list`

För att definiera en lista bestående av litteraler eller tidigare deklarerade variabler, använd funktionen `list`:

    (list 5 4 3 a b c)

Detta kommer sätta ihop och returnera en lista som innehåller värdena som hålls av variablerna `a`, `b` och `c`. Till exempel:

            (let*  (
                      (a 1)
                      (b 2)
                      (c 3)
                   )

                   (list 5 4 3 a b c)
            )

Denna kod skapar listan `(5 4 3 1 2 3)`.

#### 3.3.5. Komma åt värden i en lista

För att komma åt värdena i en lista, använd funktionerna `car` and `cdr`, vilka returnerar det första elementet i listan respektive resten av listan. Dessa funktioner delar upp listan i den huvud::svans-konstrukt jag nämnde tidigare.

#### 3.3.6. Funktionen `car`

`car` returnerar det första elementet i listan (listans huvud). Listan behöver vara skild från null (inte tom). Därmed returnerar det följande det första elementet i listan:

    (car '("första" 2 "tredje"))

som är:

    "första"

#### 3.3.7. Funktionen `cdr`

`cdr` returnerar resten av listan efter det första elementet (listans svans). Om det bara finns ett element i listan returnerar det en tom lista.

    (cdr '("första" 2 "tredje"))

returnerar:

    (2 "tredje")

medan den följande:

    (cdr '("en och endast en"))

returnerar:

    ()

#### 3.3.8. Komma åt andra element i en lista

OK, fint, vi kan få det första elementet i en lista, såväl som resten av listan, men hur gör vi för att komma åt det andra, tredje eller andra element i en lista? Det finns flera ”bekvämlighets”-funktioner för att komma åt exempelvis huvudet av huvudet av svansen av en lista (`caadr`), svansen av svansen av en lista (`cddr`), o.s.v.

Den grundläggande namnkonventionen är enkel: a och d representerar huvuden och svansar i listor, så

    (car (cdr (car x) ) )

kan skrivas som:

    (cadar x)

För att öva lite med liståtkomstfunktioner, försök skriva in följande (men allt på en rad om du använder konsolen). Använd olika variationer av `car` och `cdr` för att komma åt de olika elementen i listan:

            (let* (
                     (x  '( (1 2 (3 4 5) 6)  7  8  (9 10) )
                     )
                  )
                  ; placera din car/cdr-kod här
            )

Försök komma åt siffran 3 i listan med bara två funktionsanrop. Om du kan göra det är du på väg att bli en Script-Fu-mästare!

| Notera
I Scheme markerar ett semikolon (`;`) början på en kommentar. Det, och allt som följer det på samma rad, ignoreras av skripttolken, så du kan använda detta för att lägga till kommentarer för att fräscha upp minnet då du tittar på skriptet senare.

3.2. Variabler och funktioner |  | 3.4. Ditt första Script-Fu-skript

Report a bug in GIMP Rapportera ett dokumentationsfel