WAS LISP BESONDERES MACHTE
OriginalDezember 2001 (überarbeitet Mai 2002)
(Dieser Artikel entstand als Antwort auf einige Fragen auf der LL1-Mailingliste. Er ist jetzt in Revenge of the Nerds enthalten.)
Als McCarthy Lisp Ende der 1950er Jahre entwarf, war es eine radikale Abkehr von bestehenden Sprachen, von denen die wichtigste Fortran war.
Lisp verkörperte neun neue Ideen:
1. Bedingte Anweisungen. Eine bedingte Anweisung ist eine if-then-else- Konstruktion. Wir nehmen sie jetzt als selbstverständlich hin. Sie wurden erfunden von McCarthy bei der Entwicklung von Lisp. (Fortran hatte zu dieser Zeit nur einen bedingten goto, der eng an den Verzweigungsbefehl in der zugrunde liegenden Hardware angelehnt war.) McCarthy, der im Algol-Komitee saß, brachte bedingte Anweisungen in Algol ein, von wo aus sie sich auf die meisten anderen Sprachen ausbreiteten.
2. Ein Funktionstyp. In Lisp sind Funktionen Erstklassenobjekte-- sie sind ein Datentyp wie ganze Zahlen, Zeichenketten usw. und haben eine wörtliche Darstellung, können in Variablen gespeichert werden, können als Argumente übergeben werden und so weiter.
3. Rekursion. Rekursion gab es als mathematisches Konzept natürlich schon vor Lisp, aber Lisp war die erste Programmiersprache, die sie unterstützte. (Sie ist möglicherweise implizit in der Tatsache, dass Funktionen Erstklassenobjekte sind.)
4. Ein neues Konzept von Variablen. In Lisp sind alle Variablen effektiv Zeiger. Werte haben Typen, nicht Variablen, und das Zuweisen oder Binden von Variablen bedeutet das Kopieren von Zeigern, nicht dessen, worauf sie zeigen.
5. Garbage-Collection.
6. Programme, die aus Ausdrücken zusammengesetzt sind. Lisp-Programme sind Bäume von Ausdrücken, von denen jeder einen Wert zurückgibt. (In einigen Lisps können Ausdrücke mehrere Werte zurückgeben.) Dies steht im Gegensatz zu Fortran und den meisten nachfolgenden Sprachen, die zwischen Ausdrücken und Anweisungen unterscheiden.
Es war naheliegend, diese Unterscheidung in Fortran zu haben, da (nicht überraschend in einer Sprache, deren Eingabeformat Lochkarten waren) die Sprache zeilenorientiert war. Man konnte keine Anweisungen verschachteln. Und so brauchte man zwar Ausdrücke für die Mathematik, aber es gab keinen Grund, irgendetwas anderes einen Wert zurückgeben zu lassen, denn es konnte nichts darauf warten.
Diese Einschränkung verschwand mit dem Aufkommen von blockstrukturierten Sprachen, aber da war es zu spät. Der Unterschied zwischen Ausdrücken und Anweisungen war fest verankert. Er verbreitete sich von Fortran in Algol und von dort in deren Nachkommen.
Wenn eine Sprache ganz aus Ausdrücken besteht, kann man Ausdrücke beliebig kombinieren. Man kann entweder sagen (unter Verwendung der Arc-Syntax)
(if foo (= x 1) (= x 2))
oder
(= x (if foo 1 2))
7. Ein Symboltyp. Symbole unterscheiden sich von Zeichenketten dadurch, dass man Gleichheit durch Vergleichen eines Zeigers testen kann.
8. Eine Notation für Code mit Bäumen von Symbolen.
9. Die gesamte Sprache ist immer verfügbar. Es gibt keinen wirklichen Unterschied zwischen Lese-, Kompilier- und Laufzeit. Man kann Code kompilieren oder ausführen, während man liest, lesen oder ausführen, während man kompiliert, und lesen oder kompilieren zur Laufzeit.
Das Ausführen von Code zur Lesezeit ermöglicht es den Benutzern, die Syntax von Lisp umzuprogrammieren; das Ausführen von Code zur Kompilierzeit ist die Grundlage für Makros; das Kompilieren zur Laufzeit ist die Grundlage für den Einsatz von Lisp als Erweiterungssprache in Programmen wie Emacs; und das Lesen zur Laufzeit ermöglicht es Programmen, über s-Ausdrücke zu kommunizieren, eine Idee, die kürzlich als XML wiederentdeckt wurde.
Als Lisp erfunden wurde, waren all diese Ideen weit entfernt von der üblichen Programmierpra xis, die weitgehend durch die Hardware der späten 1950er Jahre bestimmt war.
Im Laufe der Zeit hat sich die Standardsprache, verkörpert in einer Reihe von populären Sprachen, allmählich in Richtung Lisp entwickelt. 1-5 sind jetzt weit verbreitet. 6 beginnt, im Mainstream aufzutauchen. Python hat eine Form von 7, obwohl es dafür keine Syntax zu geben scheint. 8, das (zusammen mit 9) die Grundlage für Lisp-Makros bildet, ist bisher immer noch einzigartig für Lisp, vielleicht weil (a) es diese Klammern erfordert oder etwas genauso Schlimmes, und (b) wenn man diese letzte Steigerung der Macht hinzufügt, man nicht mehr behaupten kann, eine neue Sprache erfunden zu haben, sondern nur ein neuer Dialekt von Lisp zu sein ; -)
Obwohl sie für heutige Programmierer nützlich sind, ist es seltsam, Lisp in Bezug auf seine Abweichungen von den zufälligen Expeditionen anderer Sprachen zu beschreiben. Das war wahrscheinlich nicht, wie McCarthy es sah. Lisp wurde nicht entworfen, um die Fehler in Fortran zu beheben; es entstand eher als Nebenprodukt eines Versuchs, Berechnung zu axiomatisieren.