문제
(면책 조항 : 나는 C# 남자입니다. 방금 Clojure를 배우기 시작했습니다.)
나는 그것이 클로 조이를 이해한다 프로그램 스스로를 조작하거나 다른 사람을 쉽게 생성 할 수있는 능력이 있습니다. 프로그램들. Clojure의 모든 것이 데이터 구조와 생성과 관련이 있습니다. 프로그램들 다른 유형의 데이터 구조를 작성하는 것과 동일합니다.
이것을 보여주는 좋은 샘플 프로그램 (또는 하나에 대한 참조)이 있습니까?
당신이 생성하는 경우 a 프로그램, 나중에 실행을 위해 해당 프로그램을 디스크로 "직렬화"할 수 있습니까?
참조를 위해 :
해결책
고려하다 (+ 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
다른 팁
Clojure는 LISP이며, 그것은 그것이 동종 언어 : 데이터와 코드 사이에는 구조적 차이가 없습니다. 그것의 끝까지 내려갑니다. 또한 확장 가능한 컴파일러가있어 매크로를 통해 구문을 확장 할 수 있습니다. 그러나 당신이 실제로 그런 것이 필요하다는 문제 진술에서 분명하지 않습니다.
기본적으로 목록을 생성하는 코드 (실제로 차세대 프로그램)를 생성하고 저장 한 다음 새 프로그램을 실행하는 코드를 실행하고 있습니다. 세대 진화에 새로운 구문이 필요하지 않으면 매크로에 의지 할 필요가 없을 것입니다.
부분적인 대답을 찾았습니다 이것 기사:
그만큼
pr
그리고prn
기능은 인쇄 및 인쇄물 상대와 같지만 출력은 Clojure 리더가 읽을 수있는 형태입니다. Clojure 데이터 구조를 직렬화하는 데 적합합니다. 기본적으로 메타 데이터를 인쇄하지 않습니다. 특수 기호를 바인딩하여 변경할 수 있습니다*print-meta*
에게true
.
이것은 적어도 내 질문의 두 번째 부분에 대답합니다.
Clojure가 Java Byte 코드로 Clojure 소스를 컴파일하므로 Fly-the-Fly "Code Generation"을 수행함에 따라 문제는 다소 오해의 소지가 있습니다.
이 특별한 경우 나는 믿는다 당신은 특히 LISP 매크로에서 흥미 롭습니다. 나는 이것들이 흥미로울 수 있다고 생각합니다.
Clojure의 매크로가 작동합니다 굉장히 유사한 일반적인 LISP 매크로 (Type-2 LISP)에, 그리고 매우 비슷한 체계 매크로가 아닙니다.
행복한 코딩.
매크로를 살펴보십시오. 예를 들어,
(defmacro defmacro-
"Same as defmacro but yields a private definition"
[name & decls]
(list* `defmacro (with-meta name (assoc (meta name) :private true)) decls))
매크로를 사용하면 거시 전파를 직렬화 할 필요가 없습니다. 컴파일은 자동으로 사용합니다.