动态让表单作为宏中的reify的一部分

时间:2011-10-27 22:48:56

标签: macros clojure reify

好的,让我们试着直截了当:我的最终目的是为用户提供一个宏作为API,如下所示:

(defscript [a b]
  (println a))

结果必须是Script协议的实例,如下所示:

(defprotocol Script
  (run [this model]))

这个想法是defscript的第一个参数是需要绑定到model中对应键的符号列表:

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

我无法想出能够有效产生这种效果的任何代码,因为我在尝试使用model参数时不断碰壁,因为在宏扩展时它只是一个符号:< / p>

(defmacro invoke-
  [params model body]
  (let [p (flatten (map (fn [x] [x (model (keyword x))]) params))]
    `(let [~@p]
       ~body)))

(defmacro defscript
  [params & body]
  `(reify Script
    (run [~'this ~'model]
      (invoke- ~params ~'model ~@body))))
如果直接调用,

invoke-可以正常工作:

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

但在defscript内使用时无效,因为model无法正确展开:

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

我怎样才能超越这一点并将各个部分粘在一起?

1 个答案:

答案 0 :(得分:4)

基本上,你的参数向量似乎是解构绑定的捷径:

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

这样,模型在运行时就会被破坏,应该是这样。