2009-10-26 3 views
15

(Отказ от ответственности:. Я C# парень, которого я только начал изучать Clojure.)Генерация кода в Clojure

Я понимаю, что программа Clojure имеет возможность управлять самостоятельно или легко генерировать другие программы , Это имеет какое-то отношение ко всему, что в Clojure является структурой данных, и что создание программ будет таким же, как создание любого другого типа структуры данных.

У кого-нибудь есть хорошая программа-образец (или ссылка на одну), которая показывает это?

Если вы создаете программу , можете ли вы «сериализовать» эту программу на диск для последующего выполнения?

Просто для справки:

  1. Я пытаюсь играть с генетическим программированием. Я хочу генерировать множество небольших программ, оценивать их и использовать успешные, чтобы создавать больше программ. См. Еще here и here.

  2. Я думаю, что здесь я неправильно использую условия. К программа Я на самом деле имею в виду список clojure и по Code Generation Я имею в виду «Генерация списков». Мне просто нужен список, чтобы содержать фактические вызовы функций и параметры. Мне нужно будет иметь возможность контролировать, когда этот список будет «выполнен».

ответ

27

Рассмотрите (+ 1 2). В качестве данных это связанный список из трех элементов: Символ + и два целых числа. Как код, это вызов функции, говорящий «Вызвать функцию с именем + с этими двумя целыми в качестве аргументов и дать мне результат». Вы можете сделать что-нибудь в этом списке, что вы можете сделать с любым другим списком данных. Вы также можете получить eval, чтобы получить результат.

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

Найдено частичный ответ в this статьи:

pr и prn функции подобны их печати и Println прототипов, но их выход находится в форме, которая может быть считана Clojure читатель. Они подходят для сериализации структур данных Clojure . По умолчанию они не распечатывают метаданные. Это может быть изменено путем привязки специального символа *print-meta* к true.

Это, по крайней мере, отвечает на вторую часть моего вопроса.

2

Взгляните на макросы. Например,

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

С помощью макросов вам не нужно сериализовывать макрорасширение; компилятор будет использовать его автоматически.

5

Clojure - это LISP, а это означает, что это язык homoiconic: структурных различий между данными и кодом нет. Его списки полностью вниз. Он также имеет расширяемый компилятор, который позволяет расширять синтаксис с помощью макросов. Но неясно из вашего заявления о том, что вам действительно нужна такая вещь.

Вы в основном используете код, который генерирует списки (которые являются действительно следующими ген-программами), сохраняя их, а затем запуская новые программы. Если ваша эволюция поколений не потребует нового синтаксиса, вам, вероятно, не нужно будет прибегать к макросам.

+0

Это именно то, что я хочу! Если я правильно понимаю, каждая «программа» будет списком. Мне просто нужен способ «сгенерировать» этот список с вызовами функций и параметрами, а затем «выполнить» этот список, как только я закончу. Мне кажется, мне просто нужно сгенерировать список с префиксом цитаты, чтобы список не был «оценен». –

+0

Точно. Вы захотите прочитать и понять эту страницу: http://clojure.org/reader – alphazero

3

Вопрос несколько вводит в заблуждение, поскольку Clojure также выполняет «генерации кода» на лету, поскольку он компилирует источник Clojure в Java-байт-код.

В данном конкретном случае Я считаю, что вам интересны в Lisp Macros, в частности. Я думаю, что это может быть интересно:

Clojure documentation itself

Video, Macros (in Clojure) in 20 minutes

Standard issue: Wikipedia - Clojure

Обратите внимание, что макросы в Clojure работают очень похожий к макросам Common Lisp (тип-2 LISP), а не довольно-очень-то вроде макросов схемы.

Счастливое кодирование.

+0

Помните, я парень C#. Я определенно злоупотребляю термином «генерация кода» здесь. Я думаю, что я действительно пытаюсь сказать «Генерация списков», но список должен содержать фактические вызовы функций. –

Смежные вопросы