2014-05-12 3 views
1

이 경우 사용 가능한 케이스는 생각할 수 없지만 Clojure의 매크로를 사용하여 내 마음을 감싸기위한 연습으로, 매크로를 작성하려고합니다. 두 개의 심볼에 할당 된 값을 바꿀 것입니다.두 기호의 값을 교환하는 매크로 작성하기

방법 1 :

(defmacro swap [x y] 
    `(let [tmp# ~x] 
    (def x ~y) 
    (def y ~tmp#))) 

방법 2 :

(def four 4) 
(def five 5) 

(swap four five) 

(printf "four: %d\nfive: %d" four five) 
: 여기
(defmacro swap [x y] 
    `(let [tmp# ~x] 
    (alter-var-root #'x (fn [] ~y)) 
    (alter-var-root #'y (fn [] ~tmp#)))) 

내가 그것을 테스트하는 데 사용하는 코드입니다

는 여기에 내가 시도 두 가지입니다

예상 출력 :

four: 5 
five: 4 

그러나 두 버전의 매크로를 사용하면 java.lang.RuntimeException: Unable to resolve symbol: tmp# in this context이됩니다. 자동 gensym을 잘못 사용하고 있습니까?

는 방법 1을 사용하여, 나는 그러나 내가 교체되지 않은 출력 four: 4\nfive: 5을 얻을, (tmp# 전에 ~을 복용)이 (def y tmp#)))에 마지막 줄을 변경하여 실행 얻을 수있었습니다.

+1

힌트 : 당신이 잘못 될 곳을보기 위해'(macroexpand-1 '(swap four five))'를 사용하십시오. – Alex

답변

2

사실 이와 같은 돌연변이 변이가 좋지 않다는 사실을 무시하면 어쨌든 그것을 수행하기를 원한다고 가정 해 봅시다. 당신은 당신이 xy에 인용을 끝내을 놓치고 tmp#

  • 을 원하는 ~tmp#, 상 인용을 끝내이

    • : 귀하의 문제는 두 가지입니다 당신은 (def ~x ~y)(def ~y tmp#)
    원하는

    작성한 버전은 사용자가 제공 한 vars를 수정하는 대신 항상 xy이라는 vars에 할당합니다.

  • +0

    A-ha! 그것은 그것을 고쳤다. 감사! 세미 - 관련 노트에서,'alter-var-root' 버전을 작동 시키려면'alter-var-root' 라인을 예를 들어'. '(alter-var-root (var ~ x) (fn [_ #] ~ y))'를 사용하십시오. 내 중간 gensym var'tmp #'를 부적절하게 따옴표로 묶었을뿐 아니라'x'와'y'를 인용 부호로 묶지 않았을뿐만 아니라, 익명의 함수가 잘못된 아리 티를 가졌습니다. –

    관련 문제