3.3. Listen, Listen und noch mehr Listen

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 <code>let*</code> 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 <code>"GIMP"</code>, der Liste <code>(1 2 3)</code> etc.

Es ist hilfreich, sich Listen zusammengesetzt aus einem „Kopf“ (head) und einem „Rest[15] (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.

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 (<code>caadr</code>) oder den Rest eines Restes (<code>cddr</code>) 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 <code>car</code>s und <code>cdr</code>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.

[Note] Anmerkung

In Scheme kennzeichnet ein Semikolon ("<code>;</code>") einen Kommentar. Das Semikolon und alles folgende in derselben Zeile wird vom Scheme-Interpreter ignoriert. Sie können das also verwenden, um Kommentare hinzuzufügen und Ihrem Gedächtnis auf die Sprünge zu helfen, wenn Sie sich das Skript später anschauen.



[15] beziehungsweise (wörtlich) „Schwanz“ oder „Ende