【问题标题】:Dynamic let form as part of reify within a macro动态 let 形式作为宏内 reify 的一部分
【发布时间】: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 中提供的功能隐约相似。

标签: macros clojure reify


【解决方案1】:

看来,您的参数向量基本上是解构绑定的捷径:

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

这样,模型在运行时被解构,这是应该的。

【讨论】:

    猜你喜欢
    • 2018-05-29
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 2019-09-12
    • 2012-08-31
    • 2019-04-02
    • 2020-07-31
    相关资源
    最近更新 更多