WAS LISP ANDERS MACHTE
OriginalDezember 2001 (rev. Mai 2002)
(Dieser Artikel entstand als Antwort auf einige Fragen in der LL1 Mailingliste. Er ist jetzt in Revenge of the Nerds integriert.)
Als McCarthy Lisp Ende der 1950er Jahre entwarf, war es ein radikaler Bruch mit bestehenden Sprachen, von denen die wichtigste Fortran war.
Lisp verkörperte neun neue Ideen:
1. Bedingungen. Eine Bedingung ist ein if-then-else Konstrukt. Wir halten diese heute für selbstverständlich. Sie wurden von McCarthy erfunden im Verlauf der Entwicklung von Lisp. (Fortran hatte zu dieser Zeit nur ein bedingtes goto, das eng auf der Sprunganweisung in der unterliegenden Hardware basierte.) McCarthy, der im Algol-Komitee war, brachte Bedingungen in Algol ein, von wo sie sich auf die meisten anderen Sprachen verbreiteten.
2. Ein Funktionstyp. In Lisp sind Funktionen erstklassige Objekte – sie sind ein Datentyp wie Ganzzahlen, Strings, usw., haben eine literale Darstellung, können in Variablen gespeichert, als Argumente übergeben werden und so weiter.
3. Rekursion. Rekursion existierte natürlich als mathematisches Konzept vor Lisp, aber Lisp war die erste Programmiersprache, die sie unterstützte. (Es ist arguably implizit, dass Funktionen erstklassige Objekte 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, Zeiger zu kopieren, nicht das, worauf sie zeigen.
5. Garbage-Collection.
6. Programme, die aus Ausdrücken bestehen. 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 natürlich, diese Unterscheidung in Fortran zu haben, weil (nicht überraschend in einer Sprache, in der das Eingabeformat Lochkarten waren) die Sprache zeilenorientiert war. Man konnte Anweisungen nicht schachteln. Und so, während man Ausdrücke für mathematische Operationen benötigte, gab es keinen Grund, dass irgendetwas anderes einen Wert zurückgibt, weil es nichts geben konnte, das darauf wartete.
Diese Einschränkung verschwand mit dem Aufkommen blockstrukturierter Sprachen, aber bis dahin war es zu spät. Die Unterscheidung zwischen Ausdrücken und Anweisungen war verfestigt. Sie verbreitete sich von Fortran über Algol und dann zu beiden ihren Nachkommen.
Wenn eine Sprache vollständig aus Ausdrücken besteht, kann man Ausdrücke nach Belieben zusammensetzen. Man kann entweder sagen (mit Arc Syntax)
(if foo (= x 1) (= x 2))
oder
(= x (if foo 1 2))
7. Ein Symboltyp. Symbole unterscheiden sich von Strings darin, dass man die Gleichheit testen kann, indem man einen Zeiger vergleicht.
8. Eine Notation für Code unter Verwendung von Bäumen von Symbolen.
9. Die gesamte Sprache immer verfügbar. Es gibt keine wirkliche Unterscheidung zwischen Lesezeit, Kompilierzeit und Laufzeit. Man kann Code kompilieren oder ausführen, während man liest, Code lesen oder ausführen, während man kompiliert, und Code zur Laufzeit lesen oder kompilieren.
Code zur Lesezeit auszuführen, ermöglicht es Benutzern, die Syntax von Lisp neu zu programmieren; Code zur Kompilierzeit auszuführen, ist die Grundlage für Makros; Kompilieren zur Laufzeit ist die Grundlage für die Verwendung von Lisp als Erweiterungssprache in Programmen wie Emacs; und Lesen zur Laufzeit ermöglicht es Programmen, mithilfe von s-Ausdrücken zu kommunizieren, einer Idee, die kürzlich als XML neu erfunden wurde.
Als Lisp erstmals erfunden wurde, waren all diese Ideen weit entfernt von der gewöhnlichen Programmierpraxis, die größtenteils von der Hardware bestimmt wurde, die Ende der 1950er Jahre verfügbar 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 anscheinend keine Syntax gibt. 8, die (mit 9) das möglich macht, was Lisp-Makros ermöglicht, ist bisher immer noch einzigartig für Lisp, vielleicht weil (a) es diese Klammern erfordert oder etwas ebenso Schlechtes, und (b) wenn man diesen letzten Kraftzuwachs hinzufügt, kann man nicht mehr behaupten, eine neue Sprache erfunden zu haben, sondern nur einen neuen Dialekt von Lisp entworfen zu haben ; -)
Obwohl nützlich für heutige Programmierer, ist es seltsam, Lisp in Bezug auf seine Abweichung von den zufälligen Notlösungen anderer Sprachen zu beschreiben. Das war wahrscheinlich nicht, wie McCarthy darüber dachte. Lisp wurde nicht entworfen, um die Fehler in Fortran zu beheben; es entstand eher als Nebenprodukt eines Versuchs, Berechnung zu axiomatisieren.