【发布时间】:2011-12-16 22:10:11
【问题描述】:
好的,让我们试着弄清楚这一点:我的最终目的是为用户提供一个宏作为 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 参数时经常碰壁,因为在宏扩展时它只是一个符号:
(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
我怎样才能越过这一点并将各个部分粘合在一起?
【问题讨论】:
-
您所描述的内容与
clojure.template中提供的功能隐约相似。