55 Stimmen

Ist ECMAScript wirklich ein Dialekt von Lisp?

Ein Freund machte mich auf die Willkommensbotschaft von 4. Europäisches Lisp-Symposium :

... Implementierung und Anwendung von eines der Lisp-Dialekte, einschließlich Common Lisp, Scheme, Emacs Lisp, AutoLisp, ISLISP, Dylan, Clojure, ACL2, ECMAScript , ...

und fragte dann, ob ECMAScript wirklich ein Dialekt von Lisp ist. Kann es wirklich so betrachtet werden? Und warum?

Gibt es eine gut definierte und eindeutige Reihe von Kriterien, die uns helfen zu erkennen, ob eine Sprache ein Dialekt von Lisp ist? Oder wird der Begriff "Dialekt" sehr weit gefasst (und können wir in diesem Fall Python, Perl, Haskell usw. in die Liste der Lisp-Dialekte aufnehmen?)

55voto

Pointy Punkte 387467

Brendan Eich wollte eine Scheme-ähnliche Sprache für Netscape entwickeln, aber die Realität kam dazwischen und er musste sich mit etwas begnügen, das siehe die für "normale" Menschen vage an C und Java erinnern, die aber gearbeitet wie eine funktionale Sprache.

Ich persönlich halte es für eine unnötige Übertreibung, ECMAScript als "Lisp" zu bezeichnen, aber jedem das Seine. Das Wichtigste an einem echten Lisp scheint die Eigenschaft zu sein, dass die Notation von Datenstrukturen und die Notation von Code gleich sind, und das trifft auf ECMAScript (oder Ruby oder Python oder jede andere dynamische funktionale Sprache, die no Lisp).

Caveat: Ich habe keine Lisp-Zeugnisse :-)

40voto

mblinn Punkte 3224

Das ist es nicht. Sie hat viele funktionale Wurzeln, aber das tun heutzutage auch viele andere Sprachen, die keine Lisp-Sprachen sind, wie Sie schon sagten.

Lisp-Programme haben noch eine weitere Eigenschaft, die sie zu Lisp-Programmen macht, nämlich, dass Lisp-Code in Form von Lisp-Datenstrukturen geschrieben wird (Homoikonizität). Das ist es, was das mächtige Makrosystem von Lisp ermöglicht, und warum es für Nicht-Lispianer so bizarr aussieht. Ein Funktionsaufruf ist einfach eine Liste, wobei das erste Element in der Liste der Name der Funktion ist.

Da Lisp-Code nur Lisp-Daten sind, ist es möglich, mit Metaprogrammierung einige extrem mächtige Dinge zu tun, die in anderen Sprachen einfach nicht möglich sind. Viele Lisp-Sprachen, sogar moderne wie Clojure, sind größtenteils selbst als Makros implementiert.

23voto

Matthias Benkard Punkte 15177

Auch wenn ich JavaScript nicht als Lisp bezeichnen würde, ist es meiner bescheidenen Meinung nach der Lisp-Methode ähnlicher als die meisten Mainstream-Sprachen (selbst funktionale).

Zum einen ist es, genau wie Lisp, im Wesentlichen eine einfache, imperative Sprache, die auf dem untypisierten Lambda-Kalkül basiert und von einer REPL gesteuert werden kann.

Zweitens ist es einfach, wörtliche Daten (einschließlich Code in Form von Lambda-Ausdrücken) in JavaScript einzubetten, da eine Teilmenge von ihnen JSON entspricht. Dies ist ein gängiges Lisp-Muster.

Drittens ist sein Modell der Werte und Typen sehr lispelnd. Es ist objektorientiert in einem weiten Sinne des Wortes, da alle Werte ein Konzept der Identität haben, aber es ist nicht besonders objektorientiert im engeren Sinne des Wortes. Genau wie in Lisp sind die Objekte typisiert und sehr dynamisch. Der Code ist normalerweise in Funktionseinheiten aufgeteilt, nicht in Klassen.

In der Tat gibt es ein paar (mehr oder weniger) neue Entwicklungen in der JavaScript-Welt, die die Sprache manchmal ziemlich lispy fühlen lassen. Nehmen Sie zum Beispiel jQuery. Die Einbettung von CSS-Selektoren als Subsprache ist meiner Meinung nach ein ziemlich Lisp-ähnlicher Ansatz. Oder betrachten Sie das Metaobjekt-Protokoll von ECMAScript Harmony: Es sieht wirklich wie eine direkte Portierung von Common Lisp aus (viel mehr als die Metaobjektsysteme von Python oder Ruby!). Die Liste lässt sich fortsetzen.

In JavaScript fehlen Makros und eine sinnvolle Implementierung einer REPL mit Editorintegration, was bedauerlich ist. Natürlich sind auch Einflüsse aus anderen Sprachen deutlich sichtbar (und das nicht unbedingt auf eine schlechte Art und Weise). Dennoch gibt es ein erhebliches Maß an kultureller Kompatibilität zwischen dem Lisp- und dem JavaScript-Lager. Einiges davon mag zufällig sein (wie das jüngste Aufkommen der JavaScript-JIT-Kompilierung), einiges systematisch, aber es ist definitiv vorhanden.

12voto

Kaz Punkte 51547

Wenn Sie ECMAScript Lisp nennen, behaupten Sie im Grunde, dass jede dynamische Sprache Lisp ist. Da wir bereits eine "dynamische Sprache" haben, reduzieren Sie "Lisp" auf ein nutzloses Synonym dafür, anstatt ihm eine spezifischere Bedeutung zu geben.

Lisp sollte sich korrekt auf eine Sprache mit bestimmten Eigenschaften beziehen.

Eine Sprache ist Lisp, wenn:

  • Sein Quellcode besteht aus baumstrukturierten Daten, die in Form von verschachtelten Listen ausgedruckt werden. Jede mögliche Baumstruktur hat eine Darstellung in der entsprechenden Notation und kann als Konstrukt mit einer Bedeutung versehen werden; die Notation selbst muss nicht erweitert werden, um die Sprache zu erweitern.

  • Die baumstrukturierten Daten sind eine Hauptdatenstruktur in der Sprache selbst, die Programme anfällig für Manipulationen durch Programme macht.

  • Die Sprache hat den Datentyp Symbol. Symbole haben eine gedruckte Darstellung, die interniert Wenn zwei oder mehr Instanzen der gleichen gedruckten Notation für ein Symbol in der Notation erscheinen, bezeichnen sie alle dasselbe Objekt.

    • Die Haupttugend eines Symbolobjekts besteht darin, dass es sich von allen anderen Symbolen unterscheidet. Symbole werden in der Semantik von Lisp-Programmen auf unterschiedliche Weise mit verschiedenen anderen Entitäten gepaart und dienen so als Namen für diese Entitäten.
    • Ein Lisp-Dialekt hat zum Beispiel typischerweise Variablen, genau wie andere Sprachen. In Lisp werden die Variablen durch Symbole (die Objekte im Speicher) und nicht durch Textnamen bezeichnet. Wenn ein Teil eines Lisp-Programms eine Variable definiert a ist die Syntax dafür a ist ein Symbolobjekt und nicht die Zeichenkette "a" , was für den Druck nur der Name des Symbols ist. Ein Verweis auf die Variable, der Ausdruck geschrieben als a an anderer Stelle im Programm, ist ebenfalls ein on-Objekt. Aufgrund der Funktionsweise von Symbolen handelt es sich um dasselbe Objekt; diese Objektgleichheit verbindet dann den Verweis mit der Definition. Objektgleichheit kann implementiert werden als Zeigergleichheit auf der Ebene der Maschine. Wir wissen, dass zwei Symbolwerte gleich sind, weil sie Zeiger auf denselben Speicherplatz im Heap sind (ein Objekt vom Typ Symbol).
    • Ein Beispiel dafür ist der NewLisp-Dialekt, der über eine nicht-traditionelle Speicherverwaltung für die meisten Datentypen, einschließlich verschachtelter Listen macht eine Ausnahme für Symbole, indem es sie auf die oben beschriebene Weise verhält. Ohne dies wäre es nicht Lisp. Zitat: "Objekte in newLISP ( ohne Symbole und Kontexte) werden per Wertkopie an andere benutzerdefinierte Funktionen übergeben. Infolgedessen benötigt jedes newLISP-Objekt nur eine Referenz." [Hervorhebung von mir]. Auch die Weitergabe von Symbolen, z. B. durch Wertkopie, würde ihre Identität zerstören: Eine Funktion, die ein Symbol empfängt, würde nicht das ursprüngliche Symbol erhalten und daher dessen Identität nicht korrekt empfangen.
  • Zusammengesetzte Ausdrücke in einer Lisp-Sprache - also solche, die keine einfachen Primärausdrücke wie Zahlen oder Zeichenketten sind - bestehen aus einer einfachen Liste, deren erstes Element ein Symbol ist, das die Operation angibt. Die verbleibenden Elemente, sofern vorhanden, sind Argumentausdrücke. Der Lisp-Dialekt wendet eine Art von Auswertungsstrategie an, um den Ausdruck auf einen Wert zu reduzieren und eventuelle Nebeneffekte hervorzurufen.

  • Ich würde vorläufig argumentieren, dass Listen, die aus binären Zellen bestehen, die Wertepaare enthalten und durch ein spezielles leeres Listenobjekt abgeschlossen werden, wahrscheinlich als Teil der Definition von Lisp betrachtet werden sollten: die ganze Angelegenheit, dass man aus einer bestehenden Liste eine neue Liste machen kann, indem man ein neues Element an den Anfang stellt, und die einfache Rekursion auf den "ersten" und den "Rest" einer Liste und so weiter.

Und dann würde ich genau hier aufhören. Einige Leute glauben, dass Lisp-Systeme interaktiv sein müssen: eine Umgebung mit einem Hörer bereitstellen, in der alles veränderbar ist und jederzeit neu definiert werden kann und so weiter. Manche glauben, dass Lisp erstklassige Funktionen haben muss: dass es eine lambda Operator und so weiter. Eingefleischte Traditionalisten könnten sogar darauf bestehen, dass es sein muss car y cdr Funktionen, die gepunktete Paarnotation, die unzulässige Listen unterstützt, und die Tatsache, dass Listen aus Zellen bestehen müssen und durch das Symbol nil die die leere Liste bezeichnet, und auch ein boolesches false. Das Bestehen auf car y cdr erlaubt es Scheme, ein Lisp zu sein, aber nil wobei der Listenabschluss und falsche Regeln

Je mehr wir jedoch in die Definition von "Lisp-Dialekt" eindringen, desto politischer wird es; die Leute regen sich darüber auf, dass ihr Lieblingsdialekt (den sie vielleicht selbst entwickelt haben) aufgrund einer Formalität ausgeschlossen wird. Das Beharren auf car y cdr erlaubt es Scheme, ein Lisp zu sein, aber nil als Listenabschluss und falsch schließt es aus. Was, Scheme ist kein Lisp?

Ausgehend von den obigen Ausführungen ist ECMAScript also kein Dialekt von Lisp. Allerdings enthält eine ECMAScript-Implementierung Funktionalität, die als Lisp-Dialekt dargestellt werden kann und zahlreiche solche Dialekte entwickelt worden sind . Jemand, der aus emotionalen Gründen möchte, dass ECMAScript als Lisp angesehen wird, sollte sich vielleicht damit zufrieden geben, dass die Semantik zur Unterstützung von Lisp vorhanden ist und nur eine geeignete Schnittstelle zu dieser Semantik benötigt wird, die in ECMAScript entwickelt werden kann und mit ECMAScript-Code interoperabel ist.

7voto

Eric H. Punkte 485

Ja, das ist sie. Ich zitiere Crockford:

"JavaScript hat viele Gemeinsamkeiten mit Scheme. Es ist eine dynamische Sprache. Sie hat einen flexiblen Datentyp (Arrays), der leicht s-Ausdrücke simulieren kann. Und am wichtigsten ist, dass Funktionen Lambdas sind.

Aufgrund dieser großen Ähnlichkeit können alle Funktionen in [der rekursiven Programmierfibel] 'The Little Schemer' in JavaScript geschrieben werden."
http://www.crockford.com/javascript/little.html

Zum Thema Homoikonizität würde ich empfehlen, dieses Wort zusammen mit JavaScript zu suchen. Zu sagen, dass es "nicht homoikonisch" ist, ist wahr, aber nicht das Ende der Geschichte.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X