Vi har tränat dig i variabler och funktioner, och går nu in i de dunkla kärr som är Schemes listor.
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.
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.
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.
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)
.
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.
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"
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:
()
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 ( |