2009-10-26 15 views
15

(Negación:. Soy un tipo C# Me acaba de comenzar el aprendizaje de Clojure.)generación de código en Clojure

entiendo que un programa de Clojure tiene la capacidad de manipular sí o fácilmente generar otros programas . Tiene algo que ver con que todo en Clojure sea una estructura de datos y que generar los programas sería lo mismo que crear cualquier otro tipo de estructura de datos.

¿Alguien tiene un buen programa de muestra (o una referencia a uno) que muestra esto?

Si genera un programa , ¿puede "serializar" ese programa en el disco para su posterior ejecución?

Sólo como referencia:

  1. estoy tratando de jugar con la programación genética. Quiero generar muchos pequeños programas, evaluarlos y usar los exitosos para generar más programas. Ver más here y here.

  2. Creo que estoy haciendo un uso indebido de los términos aquí. Por programa En realidad me refiero a una lista clojure y por Generación de código Me refiero a "Generación de lista". Solo necesito que la lista contenga llamadas y parámetros de funciones reales. Tendría que poder controlar cuándo se "ejecuta" esta lista.

Respuesta

27

Considerar (+ 1 2). Como datos, es una lista vinculada de tres elementos: el Símbolo + y dos enteros. Como código, es una llamada a función, que dice "Llamar a la función llamada + con estos dos enteros como argumentos y darme el resultado". Puede hacer cualquier cosa en esta lista que pueda hacer con cualquier otra lista de datos. También puede eval para obtener un resultado.

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 
4

encontrado una respuesta parcial en this artículo:

El pr y prn funciones son como su impresión y homólogos println, pero su salida está en una forma que puede ser leído por el Lector de Clojure Ellos son adecuados para la serialización de estructuras de datos Clojure . De forma predeterminada, no hacen metadatos de impresión. Esto puede ser cambiado vinculando el símbolo especial *print-meta* al true.

Esto al menos responde a la segunda parte de mi pregunta.

2

Eche un vistazo a las macros. Por ejemplo,

(defmacro defmacro- 
    "Same as defmacro but yields a private definition" 
    [name & decls] 
    (list* `defmacro (with-meta name (assoc (meta name) :private true)) decls)) 

Con las macros, no necesita serializar la macroexpansión; la compilación lo usará automáticamente.

5

Clojure es un LISP, y eso significa que es un lenguaje homoiconic: no hay una distinción estructural entre los datos y el código. Sus listas todo el camino hacia abajo. También tiene un compilador extensible que le permite extender la sintaxis a través de macros. Pero no está claro en su declaración de problema que realmente necesite tal cosa.

Básicamente está ejecutando código que genera listas (que son realmente programas de próxima generación), las guarda y luego ejecuta los nuevos programas. A menos que su evolución generacional requiera una nueva sintaxis, probablemente no necesite recurrir a macros.

+0

¡Esto es exactamente lo que estoy buscando! Si entiendo correctamente, cada "programa" va a ser una lista. Solo necesito una forma de "generar" esa lista con llamadas a funciones y parámetros y luego "ejecutar" esa lista una vez que haya terminado. Creo que solo necesito generar la lista con el prefijo de una cita, para que la lista no sea "evaluada". –

+0

Exactamente. Querrá leer y comprender esta página: http://clojure.org/reader – alphazero

3

La pregunta es algo engañosa ya que Clojure también realiza la "generación de código" sobre la marcha, ya que compila la fuente Clojure en Java Byte Code.

En este caso particular, creo que es interesante en Lisp Macros en particular. Creo que estos le pueden interesar:

Clojure documentation itself

Video, Macros (in Clojure) in 20 minutes

Standard issue: Wikipedia - Clojure

Tenga en cuenta que las macros en Clojure trabajan muy similar a las macros Common Lisp (un tipo-2 Lisp), y no bastante parecido a las macros Scheme.

Happy coding.

+0

Recuerde, soy un tipo C#. Definitivamente estoy haciendo un uso indebido del término "generación de código" aquí. Creo que lo que realmente trato de decir es "Generación de listas", pero la lista debe contener llamadas a funciones reales. –