Domanda

(Dichiarazione di non responsabilità: sono un tipo C #. Ho appena iniziato a studiare Clojure.)

Comprendo che un programma Clojure ha la capacità di manipolarsi o generare facilmente altri programmi . Ha qualcosa a che fare con tutto ciò che Clojure è una struttura di dati e che la generazione di programmi equivale a creare qualsiasi altro tipo di struttura di dati.

Qualcuno ha un buon programma di esempio (o un riferimento a uno) che mostra questo?

Se generi un programma , puoi " serializzare " quel programma su disco per una successiva esecuzione?

Solo per riferimento:

  1. Sto provando a giocare con la programmazione genetica. Voglio generare molti piccoli programmi, valutarli e utilizzare quelli di successo per generare più programmi. Vedi di più qui e qui .

  2. Penso di aver abusato dei termini qui. Per programma intendo effettivamente un elenco di clojure e per Generazione di codice intendo "Generazione di elenchi". Ho solo bisogno che l'elenco contenga chiamate e parametri di funzioni reali. Dovrei essere in grado di controllare quando questo elenco viene "eseguito".

È stato utile?

Soluzione

Prendi in considerazione (+ 1 2) . Come dati, è un elenco collegato di tre elementi: il simbolo + e due numeri interi. Come codice, è una chiamata di funzione, che dice " Chiama la funzione chiamata + con questi due numeri interi come argomenti e dammi il risultato " ;. Puoi fare qualsiasi cosa in questo elenco e fare qualsiasi altro elenco di dati. Puoi anche eval per ottenere un risultato.

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

Altri suggerimenti

Clojure è un LISP e ciò significa che è un omoiconico : non esiste distinzione strutturale tra dati e codice. Elenca fino in fondo. Ha anche un compilatore estensibile che consente di estendere la sintassi attraverso le macro. Ma non è chiaro dalla tua affermazione sul problema che hai davvero bisogno di una cosa del genere.

In pratica stai eseguendo codice che genera elenchi (che sono veramente programmi di prossima generazione), salvandoli e quindi eseguendo i nuovi programmi. A meno che la tua evoluzione generazionale non richieda una nuova sintassi, probabilmente non dovrai ricorrere a macro.

Trovato una risposta parziale in questo articolo:

  

Le funzioni pr e prn sono simili   le loro controparti stampate e stampate,   ma il loro output è in una forma che può   essere letto dal lettore Clojure. Essi   sono adatti per serializzare Clojure   strutture di dati. Per impostazione predefinita, lo fanno   non stampare i metadati. Questo può essere   modificato vincolando il simbolo speciale    * print-meta * su true .

Questo almeno risponde alla seconda parte della mia domanda.

La domanda è alquanto fuorviante poiché Clojure esegue anche al volo la "generazione di codice". mentre compila la sorgente Clojure in Java Byte Code.

In questo caso particolare, credo che tu sia interessante in particolare in Macro Lisp. Penso che questi possano essere interessanti:

Documentazione Clojure stessa

Video, Macro (in Clojure) tra 20 minuti

Problema standard: Wikipedia - Clojure

Nota che le macro in Clojure funzionano molto simili alle macro di Lisp comuni (un lisp di tipo 2) e non a macro di schemi abbastanza simili.

Buona codifica.

Dai un'occhiata alle macro. Ad esempio,

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

Con le macro, non è necessario serializzare la macroespansione; la compilazione lo utilizzerà automaticamente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top