Frage
(Disclaimer:.. Ich bin ein C # Typ, den ich habe lernen Clojure gerade begonnen)
Ich verstehe, dass ein Clojure Programm die Fähigkeit, sich selbst zu manipulieren, hat oder leicht zu erzeugen andere Programme . Es hat etwas mit allem, was in Clojure zu tun eine Datenstruktur ist, und dass Erzeugung Programme wäre das gleiche wie jede andere Art von Datenstruktur zu schaffen.
Hat jemand ein gutes Beispielprogramm (oder einen Verweis auf einem), dass dies zeigt?
Wenn Sie eine Programm generieren , können Sie „serialisiert“ das Programm auf die Festplatte für die spätere Ausführung?
Just for reference:
-
Ich versuche, mit Genetic Programming zu spielen. Ich möchte viele kleine Programme erzeugen, zu bewerten, und verwenden Sie die Erfolgreichen, um weitere Programme zu generieren. Mehr sehen hier und hier .
-
Ich glaube, ich bin zu mißbrauchen Begriffe hier. Mit dem Programm Ich meine tatsächlich eine clojure Liste und von Code Generation Ich meine "List Generation". Ich brauche nur die Liste der tatsächlichen Funktionsaufrufe und Parameter enthalten. Ich müsste in der Lage sein zu steuern, wenn diese Liste wird „ausgeführt“.
Lösung
Betrachten (+ 1 2)
. Da die Daten, es ist eine verknüpfte Liste von drei Elementen: das Symbol +
und zwei ganzen Zahlen. Als Code, es ist ein Funktionsaufruf und sagte: „Rufen Sie die Funktion +
mit diesen beiden ganzen Zahlen als Argumente und geben Sie mir das Ergebnis als“. Sie können alles auf diese Liste tun, dass Sie jede andere Liste von Daten zu tun. Sie können es auch eval
ein Ergebnis zu erhalten.
user> (def x '(+ 1 2))
#'user/x
user> (first x)
+
user> (rest x)
(1 2)
user> (map class x)
(clojure.lang.Symbol java.lang.Integer java.lang.Integer)
user> (reverse x)
(2 1 +)
user> (concat x (rest x))
(+ 1 2 1 2)
user> (eval x)
3
user> (defn foo []
(let [ops '[+ - * /] ; SO's lisp-highlighting sucks
nums (repeatedly #(rand-int 5))
expr (list* (rand-elt ops) (take 10 nums))]
(prn expr)
(prn (eval expr))))
user> (foo)
(+ 4 1 0 3 2 3 4 3 1 2)
23
nil
user> (foo)
(- 1 3 2 2 1 2 1 4 0 1)
-15
nil
Andere Tipps
Clojure ist ein Lisp, und das bedeutet, dass es sich um eine homoiconic Sprache: Es gibt keine strukturelle Unterscheidung zwischen Daten und Code. Seine Listen den ganzen Weg hinunter. Es hat auch einen erweiterbaren Compiler, der die Syntax durch Makros erweitern können. Aber es ist nicht klar, aus Ihrer Problemstellung, die Sie wirklich so etwas brauchen.
Sie laufen im Grunde Code, der ihnen Listen (die wirklich Next-Gen-Programme), Speichern und dann laufen die neuen Programme erzeugt. Es sei denn, Sie wird generationsüber Evolution neue Syntax benötigt, würden Sie wahrscheinlich nicht brauchen, um Makros zu greifen.
Gefunden eine Teilantwort in diese Artikel:
Die
pr
undprn
Funktionen sind wie ihre Druck- und println Kollegen, aber ihre Leistung ist in einer Form, die kann durch die Clojure Leser gelesen werden. Sie sind geeignet für Clojure Serialisierung Datenstrukturen. Standardmäßig sie tun drucken Metadaten nicht. Das kann sein geändert, indem das Sondersymbol Bindungs*print-meta*
true
.
Das zumindest beantwortet den zweiten Teil meiner Frage.
Die Frage ist etwas irreführend, da Clojure führt auch on-the-fly "Code Generation", wie es Clojure Quelle in Java-Bytecode kompiliert wird.
In diesem speziellen Fall, Ich glaube Sie in Lisp-Makros insbesondere interessant sind. Ich denke, diese interessant sein können:
Video, Makros (in Clojure) in 20 Minuten
Standardausrüstung: Wikipedia - Clojure
Hinweis, dass Makros in Clojure arbeitet sehr ähnlich zu Common Lisp-Makros (ein Typ-2-Lisp) und nicht ganz-so-viel-wie Schema Makros.
Happy-Codierung.
Werfen Sie einen Blick auf Makros. Zum Beispiel:
(defmacro defmacro-
"Same as defmacro but yields a private definition"
[name & decls]
(list* `defmacro (with-meta name (assoc (meta name) :private true)) decls))
Mit Hilfe von Makros, Sie brauchen nicht auf die macroexpansion serialisiert aus; die Kompilierung wird es automatisch verwendet werden.