2011-05-13 3 views
2

내가 특정 형태의 확장을 피하기 다음과 같은 예를 들면 매크로를 수행하는 방법을 알아 내려고 노력하고, 매크로 일하고,Clojure의 매크로 확장

확장
 

(defmacro and 
    ([] true) 
    ([x] x) 
    ([x & next] 
    `(let [and# ~x] 
     (if and# (and [email protected]) and#)))) 
 

,

(mexpand-all '(and 1 2 3)) 

내가 *하자로 확장에서하자 중지됩니다해야 할 일이 경우,

 

(let* [and__973__auto__ 1] 
     (if and__973__auto__ 
     (let* [and__973__auto__ 2] 
       (if and__973__auto__ 3 and__973__auto__)) 
     and__973__auto__)) 
 

된다.

답변

3

재귀 매크로 확장은 확장 할 매크로이 없을 때까지 반복적으로 양식을 확장하여 작동합니다. 즉, 매크로를 재귀 적으로 확장하고 특정 양식을 무시하려면 사용자 정의 확장기를 코딩하거나 다른 사람을 찾아야합니다. 내가 어떤 실수를하는 경우

(defn my-expander [form] 
    (cond (not (list? form)) (mexpand-1 form) 
     (= (first form) 'let) form 
      :else (map my-expander (mexpand-1 form)))) 

저를 용서해주세요 :

여기에 빠른 예입니다. 나는 Clojure보다 Scheme과 CL에 훨씬 강하다.

- 편집 - 위 함수는 let 문의 하위 형식을 확장하지 않습니다.

5

어? let의 "중지"가 의미하는 바가 명확하지 않습니다. let은 clojure.core에 정의 된 매크로이며, 컴파일러는 아무 것도 모릅니다 : 만 이해합니다. 매크로가 let으로 확장 된 경우 (어떤 식 으로든) 더 이상 확장을 거부하면 컴파일되지 않습니다.

반복적으로 매크로를 확장하지 않으려 고 매크로 출력을 개별적으로 검사하려면이 mexpand-all 대신 macroexpand 또는 macroexpand-1을 사용해야합니다. 나는 mexpand-all이 어디서 왔는지 모르지만, 내가 그런 것을 필요로 할 때 clojure.walk/macroexpand-all을 사용합니다.

+0

내가하려는 것은 재귀 적으로 let 양식을 제외한 모든 항목을 확장하는 것입니다. BTW, mexpand는 contrib 매크로 - 유틸리티에서 유래합니다. –

1

macroexpand-1을 사용하면 단일 수준의 매크로 확장을 수행 할 수 있습니다. 당신의 and 매크로,이 표현을로드 한 후

:

user=> (macroexpand-1 '(and 1 2 3)) 

수익률 :

(clojure.core/let [and__1__auto__ 1] (if and__1__auto__ (clojure.core/and 2 3) and__1__auto__))