2017-01-12 1 views
0

destrucutred 인수를 사용하여 매크로를 작성하는 데 문제가 있습니다. 다음은 예입니다 : 여기매크로를 통해 destructured args 전달

(defmacro defny 
    [n args & forms] 
    `(defn ~n ~args [email protected])) 

(defmacro defnz 
    [n f args & forms] 
    `(defn ~n ~args 
    (do 
     (~f [email protected]) 
     [email protected]))) 

(defny y 
    [{:keys [value] :as args}] 
    (println "Y ARGS" args) 
    (println "Y VALUE" value)) 

(defnz z y 
    [{:keys [value] :as args}] 
    (println "Z ARGS" args) 
    (println "Z VALUE" value)) 

, 나는 같은 작업을 수행하는 두 매크로, 단순히 defn이하기를 통해 호출 defny 및 defnz을 가지고 있지만 추가 defnz의 인수와 함께 이전에 함수 본문에 호출 다른 기능을 수용 . 내가 z를 호출 할 때

, 나는 두 값과 같은 인쇄 인수를 볼 것으로 예상, 대신 내가 얻을 : 키 [1 : 왜 이런 일

(z {:value 1}) 
Y ARGS {:keys [1], :as {:value 1}} 
Y VALUE nil 
Z ARGS {:value 1} 
Z VALUE 1 
=> nil 

내가의 탈구 인수를 {볼 수 있습니다 ] : as {: value 1}}가 y로 전달되고 있지만 defnz 매크로를 수정하여 구조화 된 args를 제대로 전달할 수 있는지 모르겠습니다.

+0

이 매크로를 생산하는 어떤 코드를보고'macroexpand'와'macroexpand-1 '을보십시오. –

답변

2

쉽게 macroexpansion와 실수 볼 수 있습니다 : 당신이 올바른지

(defn z [{:keys [value], :as args}] 
    (do 
    (y [{:keys [value], :as args}]) 
    (println "Z ARGS" args) 
    (println "Z VALUE" value))) 

: 당신이 전체 인수를 y로 형성 통과,하지만 당신이 필요로하는 것을 할 것입니다

(defnz z y 
    [{:keys [value] :as args}] 
    (println "Z ARGS" args) 
    (println "Z VALUE" value)) 

은에 확장 줄을 (y args)으로 확장합니다. 여기서 args은 단순한 기호입니다.

(defmacro defnz 
    [n f args & forms] 
    `(defn ~n ~args 
    (do 
     (~f ~'args) 
     [email protected]))) 

이제 확장이 올바른 것입니다 : 당신이 "인용 인용을 끝내"트릭을 사용해야합니다 (문자 네임 스페이스 자격을 갖춘 사람을 전환하는) 매크로 내에서 작업을 수행하려면

(defn z [{:keys [value], :as args}] 
    (do (y args) (println "Z ARGS" args) (println "Z VALUE" value))) 

을하지만 오히려 나쁜 {0 : keys [value] : all-of-them}처럼 defnz에 allargs 이름이 전달 될지 정확히 알지 못하기 때문에 (defnzargs이 될 것으로 예상하므로 동적으로 수정해야합니다. defnz에있는 allargs 이름 검색 :

(defmacro defnz 
    [n f [a :as args] & forms] 
    (let [a (if (:as a) a (assoc a :as 'everything))] 
    `(defn ~n ~[a] 
     (do 
     (~f ~(:as a)) 
     [email protected])))) 

그래서 지금은 다음에 확장합니다 :

(defnz z y 
    [{:keys [value] :as args}] 
    (println "Z ARGS" args) 
    (println "Z VALUE" value)) 

;;(defn z [{:keys [value], :as args}] 
;; (do (y args) (println "Z ARGS" args) (println "Z VALUE" value))) 


(defnz z y 
    [{:keys [value] :as all-args}] 
    (println "Z ARGS" all-args) 
    (println "Z VALUE" value)) 

;;(defn z [{:keys [value], :as all-args}] 
;; (do 
;; (y all-args) 
;; (println "Z ARGS" all-args) 
;; (println "Z VALUE" value))) 

(defnz z y 
    [{:keys [value]}] 
    (println "Z ARGS" everything) 
    (println "Z VALUE" value)) 

;;(defn z [{:keys [value], :as everything}] 
;; (do 
;; (y everything) 
;; (println "Z ARGS" everything) 
;; (println "Z VALUE" value))) 
관련 문제