Wie viele Grundelemente sind erforderlich, um eine LISP-Maschine zu erstellen? Zehn, sieben oder fünf?

79

Auf dieser Seite gibt es 10 LISP-Grundelemente. Die Grundelemente sind : atom, quote, eq, car, cdr, cons, cond, lambda, label, apply.

http://hyperpolyglot.wikidot.com/lisp#ten-primitives

Stevey schätzt, dass es sieben (oder fünf) gibt:

Es ist Teil der Reinheit der Idee von LISP: Sie brauchen nur die sieben (oder sind es fünf?) Grundelemente, um die vollständige Maschine zu bauen. http://steve-yegge.blogspot.com/2006/04/lisp-is-not-acceptable-lisp.html

Was ist die Mindestanzahl von Grundelementen zum Erstellen einer LISP-Maschine (dh etwas, das eine Auswertungs- / Wertfunktion für LISP-Code ausführen kann)? (Und welche sind sie?)

(Ich kann verstehen, dass du ohne leben könntest atom, label and apply)

Falkenauge
quelle

Antworten:

58

Grundlegende Prädikate / F-Funktionen

McCarthy ‚s Grund S-Funktionen und Prädikate waren:

  1. atom

    Was notwendig war, weil Auto und CDR nur für Listen definiert sind, was bedeutet, dass Sie sich auf keine Antwort verlassen können, um anzuzeigen, was passiert ist, wenn Sie carein Atom gegeben haben.

  2. eq

    Zum Testen der Gleichheit zwischen Atomen.

  3. car

    Zur Rückgabe der ersten Hälfte (Adresse) der Cons-Zelle. (Inhalt des Adressregisters).

  4. cdr

    Zur Rückgabe der zweiten Hälfte (Dekrement) der Cons-Zelle. (Inhalt des Dekrementregisters).

  5. cons

    Zum Erstellen einer neuen Nachteile-Zelle, wobei die Adresshälfte das erste Argument für Nachteile und die Dekrementhälfte das zweite Argument enthält.

Zusammenbinden: S-Funktionen

Anschließend fügte er seiner Grundnotation hinzu, um das Schreiben von sogenannten S-Funktionen zu ermöglichen:

  1. quote

    Einen Ausdruck darstellen, ohne ihn auszuwerten.

  2. cond

    Die Grundbedingung für die zuvor beschriebenen Prädikate.

  3. lambda

    Eine Funktion bezeichnen.

  4. label

    Obwohl er dies nicht für die Rekursion benötigte, wusste er möglicherweise nichts über den Y-Kombinator ( laut Paul Graham ), fügte dies jedoch zur Vereinfachung und zur Ermöglichung einer einfachen Rekursion hinzu.


Sie sehen also, dass er tatsächlich 9 grundlegende "Operatoren" für seine Lisp-Maschine definiert hat. In einer früheren Antwort auf eine andere Ihrer Fragen habe ich erklärt, wie Sie mit diesem System Zahlen darstellen und bearbeiten können.

Die Antwort auf diese Frage hängt jedoch davon ab, was Sie von Ihrer Lisp-Maschine erwarten. Sie könnten eine ohne die labelFunktion implementieren , da Sie einfach alles funktional zusammensetzen und durch Anwenden des Y-Kombinators eine Rekursion erhalten könnten.

atomkönnte verworfen werden, wenn Sie die carOperation für zurückkehrende Atome definiert haben NIL.

Sie könnten im Wesentlichen McCarthys LISP-Maschine mit 7 dieser 9 definierten Grundelemente haben, aber Sie könnten angeblich eine präzisere Version definieren, je nachdem, wie viel Unannehmlichkeit Sie sich selbst zufügen möchten. Ich mag seine Maschine ganz gut oder die vielen Grundelemente in den neueren Sprachen wie Clojure.

Isaac
quelle
19
Der Vorschlag, dass McCarthy nichts über den Y-Kombinator wusste, scheint falsch zu sein. Auf Seite 7 von "Rekursive Funktionen ..." schreibt McCarthy: Es gibt eine Notation mit Operatoren, die als Kombinatoren bezeichnet werden, um Funktionen ohne Verwendung von Variablen zu kombinieren. Leider sind die kombinatorischen Ausdrücke für eine interessante Funktionskombination in der Regel langwierig und unlesbar.
Luser Droog
1
Hier fehlt etwas. Solch ein Lisp konnte nicht zwei Zahlen hinzufügen oder sogar verstehen, dass 12 eine Zahl ist.
Albert van der Horst
1
Es kann in der Tat! Ich habe auch einen Blog-Beitrag darüber geschrieben. blog.isaachodes.io/p/set-theory-and-lisp
Isaac
1
Natürlich würde es nicht die traditionelle Maschinendarstellung der ganzen Zahlen verwenden und wäre daher eher ineffizient.
Isaac
14

Der beste Weg, dies tatsächlich sicher zu wissen, ist, wenn Sie es implementieren. Ich habe 3 Sommer verwendet, um Zozotez zu erstellen , ein McCarty-ish LISP, das auf Brainfuck läuft .

Ich habe versucht herauszufinden, was ich brauchte und in einem Forum finden Sie einen Thread, der besagt, dass Sie nur Lambda brauchen. Auf diese Weise können Sie einen ganzen LISP in Lambda-Kalkül erstellen, den Sie möchten. Ich fand es interessant, aber es ist kaum der richtige Weg, wenn Sie etwas wollen, das irgendwann Nebenwirkungen hat und in der realen Welt funktioniert.

Für ein vollständiges Turing-LISP habe ich Paul Grahams Erklärung von McCarthys Artikel verwendet und alles, was Sie wirklich brauchen, ist:

  • Symbolauswertung
  • Sonderformular Zitat
  • Sonderform if (oder cond)
  • Sonderform Lambda (ähnlich wie Zitat)
  • Funktion Gl
  • Funktionsatom
  • Funktion Nachteile
  • Funktionsauto
  • Funktion cdr
  • Funktionsversand (Listen-Lambda)

Das ist 10. Darüber hinaus, um eine Implementierung zu haben, die Sie testen können und nicht nur auf einem Zeichenbrett:

  • Funktion gelesen
  • Funktion schreiben

Das ist 12. In meinem Zozotez habe ich auch Set und Flambda (anonyme Makros wie Lambda) implementiert. Ich könnte ihm eine Bibliothek zuführen, die jedes dynamisch gebundene Lisp (Elisp, picoLisp) mit Ausnahme der Datei-E / A implementiert (da die zugrunde liegende BF es nur stdin / stdout unterstützt).

Ich empfehle jedem, einen LISP1-Interpreter sowohl in LISP als auch (nicht in LISP) zu implementieren, um vollständig zu verstehen, wie eine Sprache implementiert wird. LISP hat eine sehr einfache Syntax und ist daher ein guter Ausgangspunkt für einen Parser. Ich arbeite derzeit an einem Schema-Compiler, der in Schema mit verschiedenen Zielen geschrieben ist (wie Stalin für Ziel C), hoffentlich BF als eines davon.

Sylwester
quelle
3
Vergleichen Sie in Bezug auf die Verwendung von nichts als Lambda mit "Ein Befehlssatz-Computer", "NAND-Logik", "SKI-Kombinator-Kalkül", ... :-)
ajm475du
2
@ ajm475du Alle diese sind die gleichen wie "Sie brauchen nur Lambda". Es ist vollständig, aber aufgrund fehlender E / A fast unmöglich zu verwenden. BF benötigt nur 6 Anweisungen, um vollständig zu sein. der Rest, wenn es praktisch sein soll.
Sylwester
1
Hmm. Was ist, wenn Sie stdin / stdout des bf-Interpreters mit einem anderen Programm verbinden, das Datei- / Io-Befehle interpretieren kann? Dann könnte bf-lisp Anforderungen schreiben und dann aus der angeforderten Datei lesen.
Luser Droog
2
@luserdroog Sie schlagen vor, stdin / stdout als Nachrichtenbus für ein Programm / Betriebssystem zu verwenden, um Systemaufrufe zu implementieren. Ich denke tatsächlich daran, das für meinen Compiler zu tun, der zu BF kompiliert wird. Z.B. Wenn Sie mehr E / A als Lesen / Schreiben verwenden, sendet das Programm eine magische Anforderungszeichenfolge, und die API würde Handhake auf die gleiche Weise auslösen, wie Sie Fehler beim Ausführen von Windows-Programmen unter DOS in den 90er Jahren erhalten haben. Beachten Sie, dass BF noch ein Terminal bereitstellen muss, also zunächst E / A, sodass es nur eine weitere Erweiterung ist.
Sylwester
10

McCarthy verwendet sieben Betreiber die ursprüngliche Lisp zu definieren: quote, atom, eq, car, cdr, consund cond. Dieser Artikel zeichnet seine Schritte nach.

Vijay Mathew
quelle
1
Er benutzte labeles tatsächlich auch , obwohl es nicht nötig war.
Isaac
2
Und er brauchte es lambdaauch.
Isaac
9
Anfangs war ich auch verwirrt, aber er definiert tatsächlich lambdaund labelin Bezug auf die sieben gegebenen Primitive. Er stellt nur vor, was er damit meint, bevor er ihre Implementierung in der Definition von evalin Abschnitt 4 angibt. Sie können sehen, dass die Implementierung von evalUnterstützung für lambda/ listohne sich selbst bietet, abhängig von beiden.
Amalloy
8

Diese FAQ besagt:

Es gibt keinen einzigen "besten" minimalen Satz von Grundelementen; Alles hängt von der Implementierung ab. Zum Beispiel muss auch etwas so Grundlegendes wie Zahlen nicht primitiv sein und kann als Liste dargestellt werden. Ein möglicher Satz von Grundelementen könnte CAR, CDR und CONS zur Manipulation von S-Ausdrücken, READ und PRINT für die Eingabe / Ausgabe von S-Ausdrücken und APPLY und EVAL für die Eingeweide eines Interpreters umfassen. Dann möchten Sie vielleicht LAMBDA für Funktionen, EQ für Gleichheit, COND für Bedingungen, SET für Zuweisung und DEFUN für Definitionen hinzufügen. QUOTE könnte auch nützlich sein.

Das kommt von der Carnegie Melon-Website der School of Computer Science.

bennybdbc
quelle
2

Paul Graham implementiert eval mit sieben .

In McCarthys Micro Manual for LISP implementiert er eval mit zehn .

Falkenauge
quelle
2

Sie benötigen lediglich eine x86- MOVAnweisung .

"Der M / o / Vfuscator (kurz 'o', klingt wie" mobfuscator ") kompiliert Programme in" mov "-Anweisungen und nur in" mov "-Anweisungen. Arithmetik, Vergleiche, Sprünge, Funktionsaufrufe und alles andere, was ein Programm benötigt, sind Alles wird durch Mov-Operationen ausgeführt. Es gibt keinen selbstmodifizierenden Code, keine durch den Transport ausgelöste Berechnung und keine andere Form des Nicht-Mov-Betrugs. "

Im Ernst, diese Grundelemente implementieren keine Lisp-Maschine. Eine Maschine benötigt Einrichtungen wie E / A und Speicherbereinigung. Ganz zu schweigen von einem Funktionsaufrufmechanismus! Okay, Sie haben sieben Grundelemente, die Funktionen sind. Wie ruft die Maschine eine Funktion auf?

Das richtige Verständnis von dem, was diese Grundelemente ermöglichen, dass sie aussetzen den Befehlssatz eines Universal - Turing - Maschine . Da diese Anweisungen "Lispy" sind, nennen wir dies durch einen Versprecher (der mit einem Lisp spricht) schleichend eine "Lisp-Maschine". "Universal" bedeutet, dass die Maschine programmierbar ist: Mit einigen Kombinationsanweisungen, die auf die Universal Turing Machine angewendet werden, können wir jede Turing Machine instanziieren. Bisher ist das alles ein rein mathematisches Konstrukt.

Um diese UTM tatsächlich zu simulieren - realisieren Sie sie physisch, um sie auf einem Computer zu erkunden -, benötigen wir eine Maschine, mit der wir tatsächlich die Formulare eingeben können, mit denen Turing-Maschinen aus Kombinationen dieser sieben Lisp-Anweisungen erstellt werden. Und wir brauchen auch irgendeine Form von Ausgabe; die Maschine, um uns zumindest "Ja", "Nein" oder "Warten Sie, ich laufe noch" zu sagen.

Mit anderen Worten, die einzige Möglichkeit, wie diese sieben Anweisungen praktisch funktionieren können, besteht darin, dass sie auf einem größeren Computer gehostet werden, der die Umgebung bereitstellt.

Beachten Sie auch, dass Grahams sieben Grundelemente keine explizite Unterstützung für Zahlen haben, sodass Sie sie aus Funktionen erstellen müssten ("Church Numbers" -Technik). Keine Produktions-Lisp-Implementierung macht so eine verrückte Sache.

Kaz
quelle
1
Liebe es. Ich würde eine Frage zu UTMs stellen, aber ich denke, Sie haben sie bereits zerschlagen. Ich versuche mir eine Frage zu überlegen, die Home Brew 8-aber Computing, UTMs und Lisp betrifft.
Hawkeye