Lisp- Eine kurze Einführung Was ist Lisp? Lisp ist eine „listen-orientierte“ Sprache; Listen werden dazu verwendet symbolische Information darzustellen. Im Bereich der K.I. gehört Lisp zu den renomiertesten Programmiersprachen. Lisp ist primär eine funktionale Sprache, abgeleitet vom Lambda-Kalkül. In Lisp kann man aber auch prozedural und objektorientiert programmieren. Zur Geschichte Lisp wurde von John McCarthy um 1958 entwickelt, speziell für „symbolisches Rechen“ im Bereich der Künstlichen Intelligenz Am Artificial Intelligenze Laboratory des MIT wurde 1960 der erste Interpreter entwickelt. 1984 Zusammenführung verschiedener Dialekte in Common Lisp. Programmierstil Lisp unterstützt verschiedene Programmierstile o Kombiniert funktionale und prozedurale Elemente. o CLOS ist eine Spracherweiterung für objekt-orientiertes Programmieren. Extrem einfache Syntax: Hauptsächlich Klammernotation Typisierung: o Ein Typsystem ist vorhanden, aber Typisierung wird nicht gefordert und von vielen Compilern nicht vollständig unterstützt. Eine Eingabe kann sofort durch einen Interpreter ausgeführt werden. Interpretation Lisp ist eine interpretative Sprache, d.h. durch Interpretation erhält jeder Ausdruck einen Wert. Die oberste Ebenen des Lisp-Systems ist ein Interpreter für Eingaben. Der Interpreter ist realisiert als eine „read-eval-print-Schleife“ Tobias Julian Hörmann Syntax und operationelle Semantik Es gibt im wesentlichen nur Atome und Listen Atome: o Zahlen: 1, 5.3, 17/12, #c(0.2 -1.9), … o Zeichen: #\c, #\o o Zeichenreihen: “string” o Symbole: benennen Variablen und Funktionen besondere Symbole sind e.g. T für true nil für false Listen: o Entweder nil oder von der Form (a1, a2, a3, ...), wobei ai ein Atom oder eine Liste ist Variablen: o Groß- und Kleinschreibung wird nicht berücksichtigt o Definition und Zuweisung an eine Variable geschieht mit setf, o (setf title „Symbolisches Rechnen“) o Variablen werden durch Symbole benannt Auswertung: o Atome, die keine Symbole sind, evaluieren auf sich selbst. o Symbole evaluieren auf den Wert der Varaible, die sie repräsentieren Quotierung Um Ausdrücke vor der Auswertung zu schützen, kann man die Spezialform quote verwenden. y ==> >> Error: The symbol Y has no global value (quote y) ==> Y 'y ==> Y Quote benötigt genau ein Argument und gibt dieses Argument unmodifiziert und nicht evaluiert zurück. Tobias Julian Hörmann Listen Konstruktion von Listen: o Nil Erzeugt leere Liste. o (cons a l) Fügt Element a an den Anfang der Liste l an. o (list a1 a2 ...) Konstruiert eine Liste der Argumente. o (append l1 l2) hängt Listen l1, l2 zusammen. Interne Darstellung von Listenstrukturen o Man kann sich ein Listenelement als aus einer Doppelzelle (cond) bestehend vorstellen, die zwei Zeiger enthält. Der linke Zeiger (car) verweist auf den Inhalt, der rechte Zeiger (cdr) verweist auf das nächste Listenelement. Identität und Gleichheit 1. Eq testet auf Identität, d.h. auf Gleichheit der Adresse (Pointervergleich) 2. Eql testet auf Gleichheit der Adresse (Pointervergleich) und Gleichheit von Zahlen 3. Equal testet auf Strukturgleichheit (Durchlaufen der Strukturen) Bemerkung: Umgangssprachlich meint man mit eql „dasselbe“ während man mit equal „das gleiche“ meint. Tobias Julian Hörmann Prädikatfunktionen Prädikatfunktionen sind Funktionen, die einen Wahrheitswert T (für true) oder nil (für false) zurückliefern. Prädikate auf Listen: o (null l) Ist l die leere Liste? o (consp l) Ist l eine zusammengesetzte Liste? o (listp l) Ist l eine Liste (vom Typ list)? o (member a l) Ist a ein Element der Liste l? Beispiele: o (null nil) ==> T o (null '(1)) ==> NIL o (member 'a '(w x a b c)) ==> (A B C) Die Funktion member im letzten Beispiel liefert statt T die Restliste, deren erstes Element das gesuchte Element ist. Funktionen als Werte In Lisp sind Funktionen Werte: Funktionen können an andere Funktionen übergeben werden Funktonen können als Resultat zurückgegeben werden Funktionen höherer Ordnung oder Funktionale sind Funktionen, deren Argumente oder Resultate wiederum Funktionen sind. Mit function erhalten wir den funktionalen Wert. Äquivalent dazu #’ o #’ cons ==> #<Compiled-Function CONS 142B4E> Funcall, Apply und Mapcar funcall erwartet als erstes Argument eine Funktion f, danach eine bestimmte Anzahl von weiteren Werten. o (funcall #’cons 1 2) ==> (1 . 2) apply erwartet als erstes Argumente eine Funktion f, danach eine Liste von Werten. o (apply #’cons '(1 2)) ==> (1 . 2) mapcar bekommt als Argument eine Funktion und eine Liste und liefert eine neue Liste, in der die Argumentfunktion auf jedes Element der Argumentliste angewandt wird. o (mapcar #’ first '( (a b) (c d) ) ) ==> (A C) Tobias Julian Hörmann Die Lamda-Funktion Die Lambda-Notation wurde von A. Church entwickelt. Er wollte eine klare Notation um Funktionen zu beschreiben: welche Parameter sie akzeptieren, was sie tun und was sie zurückliefern. Zum Beispiel wurde die Funktion, die zu einer Zahl x die Zahl 3 addiert in Lambda-Notation wie folgt geschrieben: o λ.(3 + x) McCarthy hat diese Notation für Lisp übernommen: o lambda (x) (+ 3 x) ) liefert eine anonyme Funktion Die Funktion lambda wird benutzt um eine nicht explitzit benannte Funktionsdefinition zu formulieren: Die gebundenen Parameter haben nur lokale Bedeutung, gleichnamige Atome ausserhalb der Lambda-Funktion werden dadruch nicht angesprochen. o (mapcar #’ (lambda (x) (+ x 4) ) '(1 2 3) ) ==> (5 6 7) Bindung von Variablen durch let Mit let läßt sich ein Programmblock mit lokalen Variablen bilden. o ( let ( (var-1 value-1) (var-2 value-2) ...) body ...) Jede Variable wird an den jeweiligen Wert gebunden, danach wird der Körper ausgewertet. o ( let ( (x 40) (y (+ 1 1) ) ) (+ x y) ) ==> 42 Mit let* werden die Variablen von links nach rechts gebunden; damit kann man also auch frisch eingeführte Variablen dazu benutzen, um den Wert einer neuen Variable zu berechnen. o ( let*( (x 6) (y (* x x) ) ) (+ x y) ) ==> 42 Tobias Julian Hörmann Makros Mit Makros kann Lisp-Code textuell verändert werden. Makros eignen sich: Zur Definition neuer Kontrollstrukturen Als Benutzerinterface für eingebettete Sprachen Eingebaute Makros: defun, when, dolist, ... Neue Makros kann man mit defmacro definieren (defmacro when (test consequence) (list ’if test consequence nil) ) Quellen: Common Lisp the Language, 2nd edition http://www.cs.cmu.edu/afs/cs.cmu.edu/project/airepository/ai/html/cltl/clm/node1.html Common Lisp: A Gentle Intorduction to Symbolic Computation - David S. Touretzky, Carnegie Mellon University http://www.cs.cmu.edu/~dst/LispBook/ OnLisp – Paul Graham http://lib.store.yahoo.net/lib/paulgraham/onlisp.pdf LISP – Intensivkurs Universitat Ulm Abtl. Künstliche Intelligenz - F.W. von Henke M. Luther Tobias Julian Hörmann