Laut diesem Artikel gibt die folgende Zeile des Lisp-Codes "Hello world" in der Standardausgabe aus.
(format t "hello, world")
Lisp, eine homoikonische Sprache , kann Code wie folgt als Daten behandeln:
Stellen Sie sich nun vor, wir hätten folgendes Makro geschrieben:
(defmacro backwards (expr) (reverse expr))
rückwärts ist der Name des Makros, das einen Ausdruck (als Liste dargestellt) annimmt und ihn umkehrt. Hier ist wieder "Hallo Welt", diesmal mit dem Makro:
(backwards ("hello, world" t format))
Wenn der Lisp-Compiler diese Codezeile sieht, schaut er auf das erste Atom in der Liste (
backwards
) und bemerkt, dass er ein Makro benennt. Die nicht ausgewertete Liste wird("hello, world" t format)
an das Makro übergeben, in das die Liste neu angeordnet wird(format t "hello, world")
. Die resultierende Liste ersetzt den Makroausdruck und wird zur Laufzeit ausgewertet. Die Lisp-Umgebung erkennt, dass es sich bei ihrem ersten atom (format
) um eine Funktion handelt, wertet sie aus und übergibt ihr die restlichen Argumente.
In Lisp ist diese Aufgabe einfach (korrigieren Sie mich, wenn ich falsch liege), da Code als Liste ( s-Ausdrücke ?) Implementiert ist .
Schauen Sie sich jetzt dieses OCaml-Snippet an (das keine homoikonische Sprache ist):
let print () =
let message = "Hello world" in
print_endline message
;;
Stellen Sie sich vor, Sie möchten OCaml, das im Vergleich zu Lisp eine viel komplexere Syntax verwendet, eine Homoikonizität verleihen. Wie würdest du das machen? Muss die Sprache eine besonders einfache Syntax haben, um Homoikonizität zu erreichen?
EDIT : Von diesem Thema aus habe ich einen anderen Weg gefunden, um Homoikonizität zu erreichen, der sich von dem von Lisp unterscheidet: den in der io-Sprache implementierten . Es kann diese Frage teilweise beantworten.
Beginnen wir hier mit einem einfachen Block:
Io> plus := block(a, b, a + b) ==> method(a, b, a + b ) Io> plus call(2, 3) ==> 5
Okay, der Block funktioniert also. Der Plusblock fügte zwei Zahlen hinzu.
Lassen Sie uns nun einen Blick auf diesen kleinen Kerl werfen.
Io> plus argumentNames ==> list("a", "b") Io> plus code ==> block(a, b, a +(b)) Io> plus message name ==> a Io> plus message next ==> +(b) Io> plus message next name ==> +
Heiße heilige kalte Form. Sie können nicht nur die Namen der Blockparameter abrufen. Und Sie können nicht nur eine Zeichenfolge des vollständigen Quellcodes des Blocks abrufen. Sie können sich in den Code einschleichen und die darin enthaltenen Nachrichten durchlaufen. Und das Erstaunlichste von allem: Es ist schrecklich einfach und natürlich. Getreu Ios Suche. Rubys Spiegel kann nichts davon sehen.
Aber, whoa whoa, hey jetzt, rühr das Zifferblatt nicht an.
Io> plus message next setName("-") ==> -(b) Io> plus ==> method(a, b, a - b ) Io> plus call(2, 3) ==> -1