9 Stimmen

Welche Funktionen fehlen Lisp?

Ich habe gelesen, dass die meisten Sprachen immer mehr wie Lisp werden, Funktionen übernehmen, die Lisp schon lange hat. Ich frage mich, welche Funktionen, alt oder neu, Lisp nicht hat? Mit Lisp meine ich die gebräuchlichsten Dialekte wie Common Lisp und Scheme.

1 Stimmen

Marktplatznachfrage? Pax duckt sich in Deckung :-)

10voto

jrockway Punkte 40754

Diese Frage wurde schon millionenfach gestellt, aber los geht's. Common Lisp wurde zu einer Zeit erstellt, als Menschen als billig angesehen wurden und Maschinen als teuer. Common Lisp erleichterte den Menschen die Dinge auf Kosten der Erschwernis für Computer. Lisp-Maschinen waren teuer; PCs mit DOS waren billig. Das war nicht gut für seine Popularität; Es war besser, dass einige mehr Menschen Fehler mit weniger ausdrucksstarken Sprachen machen, als einen besseren Computer zu kaufen.

30 Jahre später stellt sich heraus, dass dies nicht stimmt. Menschen sind sehr, sehr teuer (und sehr knapp; versuchen Sie mal, einen Programmierer einzustellen), und Computer sind sehr, sehr billig. Sogar billiger als Schmutz. Was die Welt von heute braucht, ist genau das, was Common Lisp angeboten hat; wenn Lisp jetzt erfunden worden wäre, würde es sehr beliebt werden. Da es sich jedoch um eine 30 Jahre alte (und mehr!) Technologie handelt, dachte niemand daran, sie zu betrachten, und erstellte stattdessen ihre eigenen Sprachen mit ähnlichen Konzepten. Das sind diejenigen, die Sie heute verwenden. (Java + Garbage Collection ist eine der großen Innovationen. Jahrelang wurde GC wegen seiner "zu langsamen" Geschwindigkeit verachtet, aber natürlich, nach etwas Forschung ist es jetzt schneller als das Verwalten von eigenem Speicher. Und auch einfacher für Menschen. Wie sich die Zeiten ändern...)

7voto

Nathan Shively-Sanders Punkte 17999
  • Pass-by-reference (C++/C#)
  • String-Interpolation (Perl/Ruby) (obwohl es ein Merkmal von CL21 ist)
  • Schöne Infix-Syntax (obwohl es nicht klar ist, ob es sich lohnt) (Python)
  • Monadische 'Iteration' Konstruktion, die für andere Zwecke überladen werden kann (Haskell/C#/F#/Scala)
  • Statische Typisierung (obwohl es nicht klar ist, ob es sich lohnt) (viele Sprachen)
  • Typinferenz (zumindest nicht im Standard) (Caml und viele andere) (obwohl CL etwas Typinferenz macht, im Gegensatz zu Python)
  • Abstrakte Datentypen (Haskell/F#/Caml)
  • Pattern Matching (Haskell/F#/Caml/Scala/andere) (in CL gibt es Bibliotheken wie optima)
  • Backtracking (obwohl es nicht klar ist, ob es sich lohnt) (Prolog)
  • ad-hoc Polymorphismus (siehe Andrew Myers' Antwort)
  • Unveränderliche Datenstrukturen (viele Sprachen) (verfügbar durch Bibliotheken, wie Fsets)
  • Lazy Evaluation (Haskell) (verfügbar durch Bibliotheken, wie clazy oder ein cl21 Modul)

(Bitte ergänzen Sie diese Liste, ich habe sie als Community-Wiki markiert.)

Dies bezieht sich nur auf die Common Lisp und Scheme Standards, da bestimmte Implementierungen viele dieser Funktionen unabhängig hinzugefügt haben. Tatsächlich ist die Frage irgendwie falsch. Es ist so einfach, Funktionen zu Lisp hinzuzufügen, dass es besser ist, eine Kernsprache ohne viele Funktionen zu haben. So können die Menschen ihre Sprache an ihre Bedürfnisse anpassen.

Natürlich packen einige Implementierungen das Kern-Lisp mit einer Menge dieser Funktionen als Bibliotheken. Zumindest für Scheme bietet PLT Scheme alle oben genannten Funktionen*, meistens als Bibliotheken. Ich kenne kein Äquivalent für Common Lisp, aber es könnte eines geben.

*Vielleicht nicht Infix-Syntax? Ich bin mir nicht sicher, ich habe nie danach gesucht.

3voto

Pillsy Punkte 9591

Für Common Lisp halte ich es für sinnvoll, die folgenden Funktionen zu einer zukünftigen Standardversion hinzuzufügen, in der lächerlich unwahrscheinlichen hypothetischen Situation, dass ein weiterer Standard erstellt wird. All dies sind Dinge, die von praktisch jeder aktiv gepflegten CL-Implementierung auf subtil inkompatible Weise bereitgestellt werden oder in weit verbreiteten und portablen Bibliotheken existieren, sodass ein Standard erhebliche Vorteile für Benutzer bringen würde, ohne Implementoren unangemessen zu belasten.

  • Einige Funktionen zum Arbeiten mit einem Betriebssystem, wie das Aufrufen anderer Programme oder das Behandeln von Befehlszeilenargumenten. Jede von mir verwendete CL-Implementierung hat etwas Ähnliches, und sie sind alle ziemlich ähnlich.

  • Unterliegende Makros oder Sonderformen für BACKQUOTE, UNQUOTE und UNQUOTE-SPLICING.

  • Das Meta-Objekt-Protokoll für CLOS.

  • Ein Protokoll für benutzerdefinierte LOOP-Klauseln. Es gibt einige andere Möglichkeiten, wie LOOP verbessert werden könnte, die wahrscheinlich nicht allzu schmerzhaft wären, wie Klauseln zum Binden mehrerer Werte oder Iteration über eine generische Sequenz (anstatt unterschiedliche Klauseln für LISTs und VECTORs zu erfordern).

  • Ein Systemdefinitionstool, das mit PROVIDE und REQUIRE integriert ist und PROVIDE und REQUIRE nicht veraltet.

  • Bessere und erweiterbarere Streamfunktionen, die es Benutzern ermöglichen, ihre eigenen Stream-Klassen zu definieren. Dies könnte etwas schwieriger sein, da es zwei konkurrierende Vorschläge gibt, Gray-Streams und "Simple-Streams", die von einigen CL-Implementierungen implementiert werden.

  • Bessere Unterstützung für "Umgebungen", wie in CLTL2 beschrieben.

  • Eine Deklaration zum Zusammenführen von Endaufrufen und eine Beschreibung der Situationen, in denen Aufrufe, die wie Endaufrufe aussehen, es nicht sind (aufgrund von UNWIND-PROTECT-Formen, DYNAMIC-EXTENT-Deklarationen, Bindungen von speziellen Variablen usw.).

  • REMOVE-IF-NOT und ähnliche nicht veralten. Den :TEST-NOT-Schlüsselwortargument und SET eliminieren.

  • Schwache Referenzen und schwache Hashtabellen.

  • Vom Benutzer bereitgestellte Hashtabellentests.

  • PARSE-FLOAT. Derzeit müssen Sie, wenn Sie aus einer Zeichenfolge eine Gleitkommazahl erstellen möchten, entweder READ verwenden (was möglicherweise Dinge tut, die Sie nicht möchten) oder Ihre eigene Analysefunktion erstellen. Das ist albern.

Hier sind noch einige ehrgeizigere Funktionen, die ich immer noch für sinnvoll halte.

  • Ein Protokoll zur Definition von Sequenzklassen, die mit den Standard generischen Sequenzfunktionen (wie MAP, REMOVE und anderen) funktionieren. Es wäre auch schön, unveränderliche Zeichenfolgen und Zellen neben ihren veränderlichen Genossen hinzuzufügen.

  • Eine reichhaltigere Auswahl an assoziativen Array/"Map"-Datentypen. Derzeit haben wir Ad-hoc-Dinge, die aus Zellen (Alisten und Plisten) und Hashtabellen erstellt sind, aber keine balancierten binären Bäume. Generische Sequenzfunktionen bereitstellen, um mit diesen zu arbeiten.

  • DEFCONSTANT so ändern, dass es etwas weniger nutzlos macht.

  • Bessere Steuerung des Lesers. Es ist ein sehr mächtiges Werkzeug, muss aber sehr vorsichtig verwendet werden, um Dinge wie das Einführen neuer Symbole zu vermeiden. Außerdem wäre es schön, wenn es bessere Möglichkeiten gäbe, Lesetabellen und benutzerdefinierte Lesesyntaxe zu verwalten.

  • Eine Lese-Syntax für "unformatierte Zeichenfolgen", ähnlich dem, was Python bietet.

  • Weitere Optionen für CLOS-Klassen und Slots, die mehr Optimierungen und bessere Leistung ermöglichen. Beispiele sind "primäre" Klassen (bei denen Sie nur eine "primäre Klasse" in der Liste der Superklassen einer Klasse haben können), "versiegelte" generische Funktionen (so dass Sie keine weiteren Methoden hinzufügen können, damit der Compiler viele mehr Annahmen darüber treffen kann) und Slots, die garantiert gebunden sind.

  • Thread-Unterstützung. Die meisten Implementierungen unterstützen entweder bereits SMP oder werden es in naher Zukunft unterstützen.

  • Mehr Verhalten von Pfadnamen festlegen. Es gibt viele unnötig lästige Inkompatibilitäten zwischen Implementierungen, wie CLISP's Beharren darauf, einen Fehler zu melden, wenn Sie PROBE-FILE auf ein Verzeichnis anwenden, oder sogar die Tatsache, dass es keine Standardfunktion gibt, die Ihnen sagt, ob ein Pfadname der Name eines Verzeichnisses ist oder nicht.

  • Unterstützung für Netzwerk-Sockets.

  • Ein gemeinsames Fremdfunktionsinterface. Es wäre unvermeidlich eine Art kleinsten gemeinsamen Nenner, aber ich denke, dass es ein echter Vorteil wäre, auf etwas verlässliches zurückgreifen zu können, selbst wenn einige der cooleren Funktionen, die einige Implementierungen bieten, immer noch auf Erweiterungen beschränkt wären.

2voto

asm Punkte 8570

Dies ist eine Antwort auf die Diskussion in den Kommentaren unter Nathans Antwort. Das ist etwas zu viel für einen Kommentar, daher füge ich es hier hinzu. Ich hoffe, dass dies nicht gegen die Etikette von Stackoverflow verstößt.

Ad-hoc-Polymorphismus wird als unterschiedliche Implementierungen basierend auf festgelegten Typen definiert. In Common Lisp können Sie mithilfe generischer Methoden etwas Ähnliches wie das Folgende definieren, das genau das ermöglicht.

;Dies ist unnötig und wird implizit erstellt, wenn nicht definiert.
;Es kann explizit bereitgestellt werden, um eine Schnittstelle zu definieren.
(defgeneric what-am-i? (ding))

;Bieten Sie eine Implementierung an, die für jeden Typ funktioniert.
(defmethod what-am-i? (ding)
  (format t "Mein Wert ist ~a~%" ding))

;Spezialisieren Sie auf ding als Ganzzahl.
(defmethod what-am-i? ((ding integer))
  (format t "Ich bin eine Ganzzahl!~%")
  (call-next-method))

;Spezialisieren Sie auf ding als Zeichenfolge.
(defmethod what-am-i? ((ding string))
  (format t "Ich bin eine Zeichenfolge!~%")
  (call-next-method))

CL-USER> (what-am-i? 25)
Ich bin eine Ganzzahl!
Mein Wert ist 25
NIL
CL-USER> (what-am-i? "Andrew")
Ich bin eine Zeichenfolge!
Mein Wert ist Andrew
NIL

1voto

sfg Punkte 479
  • Es kann schwieriger sein als in populäreren Sprachen, gute Bibliotheken zu finden.
  • Es ist nicht rein funktional wie Haskell

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