next up previous contents
Nächste Seite: Netzwerkprotokoll der Implementierung des Aufwärts: Einführung Vorherige Seite: EMACS   Inhalt

Lisp und Emacs-Lisp

Lisp (LISt Processing language) wurde ursprünglich von Professor McCarthy am Massachusetts Institute of Technology für die Erforschung künstlicher Intelligenz entwickelt. Duzende Lisp-Implementationen wurde seither entwickelt, fast alle mit eigenen Merkmalen und Vorzügen. Viele wurden von Maclisp abgeleitet, welches in den 60er Jahren am MIT entwickelt wurde. Später, 1984 haben die Abkömmlinge von Maclisp einen gemeinsamen Sprachstandard entwickelt, Common Lisp. Inzwischen entwickelten Gerry Sussman und Guy Steele am MIT einen vereinfachten, aber sehr mächtigen Lisp-Dialekt, Scheme. GNU Emacs Lisp ist weitestgehend von Maclisp und ein wenig von Common Lisp abgeleitet. Ein erfahrener Common Lisp Programmierer wird viele Ähnlichkeiten feststellen. Jedoch mussten eine Vielzahl von Eigenschaften von Common Lisp weggelassen oder vereinfacht werden, um den Speicherbedarf möglichst gering zu halten.[3]

Lisp ist eine Interpretersprache. Obwohl einige Lisp-Compiler existieren, wird Lisp hauptsächlich interpretativ abgearbeitet. Da damit zu einem Lisp-Programm auch gleich der Quelltext vorliegt und Änderungen sofort umgesetzt werden, vereinfacht sich der Entwurf und führt zu einer einfachen Erweiterbarkeit von Lisp-Programmen. Lisp unterscheidet nicht zwischen Daten und Programmtext. Unter anderem diese Uniformität von Quellcode und Daten ermöglicht die Verarbeitung hochstrukturierter symbolischer Daten. Das ursprünglich von McCarthy entwickelte Lisp war annähernd eine Eins-zu-Eins-Umsetzung des Lambda- Kalküls. Auch jetzt spielt die Auswertung von Lambda-Ausdrücken eine bedeutende Rolle in der Programmierung von Lisp-Programmen. Aus der Verwendung des Lambda-Kalküls, welches die Grundlage der Funktionalen Programmierung ist, lässt sich auch das funktionale als das bevorzugte Programmierparadigma bei der Lisp-Programmierung ableiten.

Die meisten Lisp-Dialekte, und so auch Emacs-Lisp, verwenden oder ermöglichen die Verwendung von Seiteneffekten. Ein wichtiges Merkmal von Lisp im Vergleich zu vielen anderen Programmiersprachen, ist, dass die Variablennamen zur Laufzeit erhalten bleiben. Lisp behält die Verbindung zwischen den Namen einer Variable und dem Wert der Variable bei. Für einen erweiterbaren Editor wie Emacs ist dies verbunden mit der Verwendung von globalen Variablen sehr vorteilhaft. Emacs besitzt zum Beispiel eine Variable, die Comment Start heisst, und einen String enthalten soll, welcher in einem Text einen Kommentar einleitet. Emacs verwendet die Variable für Operationen auf Kommentaren, wie das Einrücken oder Löschen von Kommentaren. Durch das Ändern dieser Variable kann ein Benutzer das Verhalten dieser Emacs-Funktionen anpassen.

Daten und Programme in Lisp sind aus symbolischen Ausdrücken aufgebaut, die entweder Atome oder Listen sind. Es existieren numerische Atome (Zahlen), Strings (Zeichenketten) und symbolische Atome (Symbole). Eine Liste besteht aus einer öffnenden Klammer gefolgt von beliebig vielen Listenelementen und einer schliessenden Klammer. Ein Listenelement ist eine Liste oder ein Atom.

Die wichtigste Datenstruktur in Lisp ist die Liste. Eine Liste ist entweder die leere Liste (nil) oder besteht aus einem Kopf (car) und einer Restliste (cdr).

In Lisp gibt es eine Vielzahl von Datentypen. Allerdings sind nicht die Variablen, sondern die Objekte selbst getypt, eine Variable kann jede Art von Lisp-Objekt speichern. Die bereitgestellten Typen umfassen Integers, Funktionen, Zeichen, Zeichenketten, Bitvektoren, Vektoren, Felder, Zahlen, Folgen, Listen und mehr.

Funktionen werden mit defun definiert. Eine Funktion kann eine beliebige Anzahl Parameter akzeptieren. Der Funktionskörper kann eine beliebige Folge symbolischer Ausdrücke sein.[5]

Eine wichtige Eigenschaft und Besonderheit von Emacs-Lisp ist die Verwendung von Dynamic Variable Scope. Das heisst, dass die Bindung einer Variablen in allen Aufrufen von Unterroutinen sichtbar ist, es sei denn, die Variable wird neu gebunden. Wird zum Beispiel verwendet:

(defun foo1 (x)
  (foo2))
(defun foo2 ()
  (+ x 5))
Dann liefert ein Aufruf von (foo1 2) 7 zurück, da foo2 beim Aufruf den Wert von foo1 für x verwendet.


next up previous contents
Nächste Seite: Netzwerkprotokoll der Implementierung des Aufwärts: Einführung Vorherige Seite: EMACS   Inhalt
Robert Hoehndorf 2002-08-22