Wir haben Ihnen etwas über Variablen und Funktionen erklärt, und nun betreten wir die düsteren Sümpfe von Schemes Listen...
Bevor wir mehr über Listen erzählen, müssen Sie den Unterschied zwischen atomaren Werten und Listen kennen.
Sie haben bereits atomare Werte gesehen, als wir im vorherigen Abschnitt Variablen initialisiert hatten. Ein atomarer Wert ist ein einzelner Wert. Zum Beispiel können wir in der folgenden Anweisung der Variablen „x“ den Wert 8 zuweisen:
(let* ( (x 8) ) x)
(Wir haben den Ausdruck x
am Ende hinzugefügt, um
den zugewiesen Wert auszugeben - normalerweise brauchen Sie das
nicht. Beachten Sie, dass sich let*
genau wie eine
Funktion verhält: Der Wert der letzten Anweisung ist der
Rückgabewert.)
Eine Variable kann sich auch auf eine Liste von Werten statt auf
einen einzelnen Wert beziehen. Um der Variablen x
die Liste der Werte 1, 3, 5 zuzuweisen, schreiben wir:
(let* ( (x '(1 3 5))) x)
Probieren Sie beide Anweisungen in der Skript-Fu-Konsole aus und achten Sie auf die Antworten. Bei der ersten Anweisung lautet sie einfach:
8
Wenn Sie aber die andere Anweisung eingeben, ist die Antwort das folgende Ergebnis:
(1 3 5)
Die erste Antwort sagt Ihnen, dass x
den
atomaren Wert 8 enthält. Aber wenn die Antwort (1 3 5) lautet,
dann heißt das, dass x
keinen atomaren Wert,
sondern eine Liste von Werten enthält. Beachten Sie, dass weder in
unserer Deklaration oder Zuweisung der Liste noch im ausgegebenen
Resultat Kommas stehen.
Die Syntax, um eine Liste zu definieren, lautet:
'(a b c)
wobei a
, b
und
c
Literale (buchstabengetreu einzugeben) sind. Wir
verwenden den Apostroph (') um anzuzeigen, dass der nachfolgende
Klammerausdruck eine Liste literaler Werte ist und nicht eine
Funktion oder ein Ausdruck.
Eine leere Liste kann wie folgt definiert werden:
'()
oder einfach:
()
Listen können sowohl atomare Werte als auch andere Listen enthalten:
(let* ( (x '("GIMP" (1 2 3) ("is" ("great" () ) ) ) ) ) x )
Beachten Sie, dass Sie nach dem ersten Apostroph keine weiteren Apostrophe mehr brauchen, wenn Sie innere Listen definieren. Probieren Sie es nun aus, kopieren Sie die Anweisung in die Skript-Fu-Konsole und schauen Sie, was sie zurück liefert.
Sie sollten bemerkt haben, dass das zurückgelieferte Ergebnis keine
Liste einzelner, atomarer Werte ist. Statt dessen ist es eine Liste
eines Literals "GIMP"
, der Liste (1 2
3)
etc.
Es ist hilfreich, sich Listen zusammengesetzt aus einem „Kopf“ (head) und einem „Rest“ [18] (tail) vorzustellen. Der Kopf ist das erste Element der Liste, der Rest alle folgenden Elemente. Sie werden gleich sehen, warum das wichtig ist, wenn wir besprechen, wie man zu Listen etwas hinzufügt und wie man auf Elemente der Liste zugreift.
Eine der üblichen Funktionen, auf die Sie treffen werden, ist die
cons
-Funktion. Sie nimmt einen Wert und fügt ihn vor
dem zweiten Argument (eine Liste) ein. Im vorigen Abschnitt habe ich
vorgeschlagen, sich die Liste aus einem Element (head) und dem Rest
(tail) zusammengesetzt vorzustellen. Genau so funktioniert
cons
- sie fügt ein Element als Listenkopf ein. Somit
können Sie eine Liste wie folgt erstellen:
(cons 1 '(2 3 4) )
Das Ergebnis ist die Liste (1 2 3 4)
.
Sie könnten auch eine Liste mit nur einem Element erstellen:
(cons 1 () )
Sie können vorher deklarierte Variablen anstelle irgendwelcher Literale verwenden, genau so, wie man es erwarten würde.
Um eine Liste aus Literalen oder vorher deklarierten Variablen
zu definieren, verwenden Sie die list
-Funktion:
(list 5 4 3 a b c)
Das wird eine Liste erstellen, die die Werte der Variablen
a
, b
und c
enthält, und diese zurückgeben. Beispiel:
(let* ( (a 1) (b 2) (c 3) ) (list 5 4 3 a b c) )
Dieser Code erzeugt die Liste (5 4 3 1 2 3)
.
Um auf Werte in einer Liste zuzugreifen, verwenden Sie die Funktionen
car
und cdr
, die das erste Element resp.
den Rest einer Liste liefern. Diese Funktionen gliedern die Liste in
die vorher erwähnte Struktur aus head
(Kopf) und tail (Rest) auf.
car
liefert das erste Element (den Kopf) einer nicht-leeren Liste.
Folgende Anweisung liefert also das erste Element der Liste:
(car '("first" 2 "third"))
nämlich:
"first"
cdr
liefert den Rest der Liste nach dem ersten Element.
Wenn die Liste nur ein Element enthält, liefert cdr
eine leere Liste.
(cdr '("first" 2 "third"))
liefert:
(2 "third")
während folgende Anweisung:
(cdr '("one and only"))
das liefert:
()
Na schön, wir können sowohl auf das erste Element als auch auf den
Rest der Liste zugreifen, aber wie kommen wir an das zweite, dritte
oder irgendein anderes Element der Liste?
Aus praktischen Gründen gibt es einige Zugriffsfunktionen, um
beispielsweise auf den Kopf eines Kopfes eines Rests
(caadr
) oder den Rest eines Restes (cddr
)
einer Liste zuzugreifen.
Die zugrunde liegende Namenskonvention ist einfach: Die „a“s und „d“s repräsentieren Köpfe beziehungsweise Reste von Listen, d.h.
(car (cdr (car x) ) )
kann geschrieben werden als:
(cadar x)
Um mit den Listenzugriffsfunktionen etwas Übung zu bekommen,
versuchen Sie mal, folgendes einzugeben (alles in einer Zeile,
falls Sie die Konsole benutzen) und verschiedene Variationen
von car
s und cdr
s auszuprobieren,
um auf verschiedene Elemente der Liste zuzugreifen:
(let* ( (x '( (1 2 (3 4 5) 6) 7 8 (9 10) ) ) ) ; place your car/cdr code here )
Versuchen Sie, mit nur zwei Funktionsaufrufen auf die Zahl 3 zuzugreifen. Wenn Sie das schaffen, sind Sie auf dem besten Wege, ein Skript-Fu-Meister zu werden.
Anmerkung | |
---|---|
In Scheme kennzeichnet ein Semikolon (" |