2011-10-27 3 views
2

좋아 내에서 구체화의 일환으로 양식을하자 처럼 보이는 Script 프로토콜의 인스턴스가 될 수 있습니다 :동적,의 직선이를 얻을려고하자 매크로

(defprotocol Script 
    (run [this model])) 

defscript에 첫 번째 인수가 model에 대응 키에 바인딩 될 필요가 기호 목록입니다되는 아이디어 :

은 16,
(.run (defscript [a b] (println a)) {:a 1}) ;; yields 1 

model 매개 변수를 사용하려고 할 때 매크로 확장시에 그냥 상징이기 때문에 나는 끊임없이 벽을 치는거야 나는 효과적으로 같은 효과를 얻을 수있는 코드를 가지고 올 수 없습니다

직접 호출하는 경우
(defmacro invoke- 
    [params model body] 
    (let [p (flatten (map (fn [x] [x (model (keyword x))]) params))] 
    `(let [[email protected]] 
     ~body))) 

(defmacro defscript 
    [params & body] 
    `(reify Script 
    (run [~'this ~'model] 
     (invoke- ~params ~'model [email protected])))) 

invoke- 잘 작동합니다 :

(invoke- [a] {:a 1} (println a)) ;; prints 1 

을하지만 제대로 확장 할 수 없습니다 defscriptmodel으로 내에서 사용하는 경우 작동하지 않습니다 :

(.run (defscript [a] (println a)) {:a 1}) ;; prints nil 

어떻게하면이 지점을 지나고 조각들을 함께 붙일 수 있습니까? 그것이 있어야로

(defscript [a b] body) -> (reify Script (run [this {:keys [a b]}] body)) 

그 방법은, 모델, 런타임에 탈구되어

+0

'clojure.template'에서 제공하는 기능과 같이 막연하게 들리는 것으로 보입니다. –

답변

4

기본적으로, 당신의 인수 벡터는 바인딩 destructuring에 대한 바로 가기 인 것 같다.

+0

정말 좋은 아주 좋은! – kotarak

+0

순수 awesomeness, 감사합니다! – skuro