Pergunta

(Disclaimer: Eu sou um cara C # Eu apenas comecei aprendendo Clojure..)

Eu entendo que um Clojure programa tem a capacidade de manipular a si mesmo ou facilmente gerar outros programas . Tem algo a ver com tudo em Clojure sendo uma estrutura de dados e que a geração de programas seria o mesmo que criar qualquer outro tipo de estrutura de dados.

Alguém tem um bom programa de amostra (ou uma referência a um) que mostra isso?

Se você gerar um programa , não é "serialize" esse programa no disco para execução posterior?

Apenas para referência:

  1. Eu estou tentando jogar com Programação Genética. Eu quero gerar um monte de pequenos programas, avaliá-los e usar os bem-sucedidos para gerar mais programas. Ver mais aqui e aqui .

  2. Eu acho que estou abusando termos aqui. Por programa eu realmente significam uma lista clojure e pela Geração de código eu quero dizer "Lista Generation". Eu só preciso a lista para conter chamadas de funções reais e parâmetros. Eu preciso ser capaz de controlar quando esta lista é "executado".

Foi útil?

Solução

Considere (+ 1 2). Conforme os dados, é uma lista encadeada de três itens: a + símbolo e dois inteiros. Como código, é uma chamada de função, dizendo "Ligue para a função chamada + com esses dois inteiros como argumentos e me dar o resultado". Você pode fazer qualquer coisa a esta lista que você pode fazer para qualquer outra lista de dados. Você também pode eval-lo para obter um 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

Outras dicas

Clojure é um LISP, e isso significa que é um homoiconic língua: não existe distinção estrutural entre os dados e o código. Suas listas de todo o caminho. Ele também tem um compilador extensível que permite estender a sintaxe através de macros. Mas não é claro a partir de sua declaração de problema que você realmente precisa de uma coisa dessas.

Você está correndo basicamente código que gera listas (que são realmente próximos programas gen), salvando-os, em seguida, executar os novos programas. A menos que sua evolução geracional exigirá nova sintaxe, você provavelmente não precisa de recorrer a macros.

Encontrado uma resposta parcial em este artigo :

As funções pr e prn são como sua impressão e contrapartes println, mas a sua saída está em um formulário que pode ser lido pelo leitor Clojure. Eles são adequados para a serialização Clojure estruturas de dados. Por padrão, eles fazem Não imprimir metadados. Isso pode ser mudou ligando o símbolo especial *print-meta* para true.

Esta, pelo menos, respostas a segunda parte da minha pergunta.

A questão é um pouco enganador como Clojure também realiza "geração de código" on-the-fly, uma vez que compila fonte Clojure em Java Código Byte.

Neste caso particular, Eu acredito você é interessante em Lisp macros em particular. Eu acho que estes podem ser interessantes:

Clojure si

documentação

Vídeo, Macros (em Clojure) em 20 minutos

questão Standard: Wikipedia - Clojure

Note que as macros no trabalho Clojure muito semelhante para macros Lisp Comum (um tipo-2 Lisp), e não é bem-assim-muito-como macros Esquema.

Happy codificação.

Dê uma olhada em macros. Por exemplo,

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

Com macros, você não precisa para serializar o macroexpansion; a compilação irá usá-lo automaticamente.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top