【问题标题】:Force expansion of an expression inside a Clojure macro强制扩展 Clojure 宏中的表达式
【发布时间】:2011-09-18 03:23:39
【问题描述】:

我正在尝试在 defprotocol 中使用 Stuart Sierra 的 do-template 宏,而 Clojure 编译器抱怨我正在重新定义 do-template——这不是我想要的:

(defprotocol AProtocol
  (a-method [_])
  (do-template [name]
    `(~(symbol (str name "-method")) [this that])
    foo
    bar
    baz))

这应该扩展为:

(defprotocol AProtocol
  (a-method [_])
  (foo-method [this that])
  (bar-method [this that])
  (baz-method [this that]))

问题(我相信)是do-template s 表达式被传递给defprotocol 未扩展。有什么办法让它在通过之前进行评估?

顺便说一句,do-template 实际上应该扩展到

(do
  (foo-method [this that])
  (bar-method [this that])
  (baz-method [this that]))

但我已经尝试过(使用手动扩展版本)并且defprotocol 可以使用嵌套的do

如何查看do-template 的实际扩展?我尝试了(macroexpand '(do-template ...))(macroexpand-1 '(do-template ...)) 并得到了:

(做 (clojure.core/seq (clojure.core/concat (clojure.core/list (符号 (str foo “-方法”)))(clojure.core/list (clojure.core/apply clojure.core/vector (clojure.core/seq (clojure.core/concat (clojure.core/list(引用用户/this)) (clojure.core/list(引用 用户/那个))))))))(clojure.core/seq (clojure.core/concat (clojure.core/list (符号 (str bar “-方法”)))(clojure.core/list (clojure.core/apply clojure.core/vector (clojure.core/seq (clojure.core/concat (clojure.core/list(引用用户/this)) (clojure.core/list(引用 用户/那个))))))))(clojure.core/seq (clojure.core/concat (clojure.core/list (符号 (str baz) “-方法”)))(clojure.core/list (clojure.core/apply clojure.core/vector (clojure.core/seq (clojure.core/concat (clojure.core/list(引用用户/this)) (clojure.core/list(引用 用户/那个))))))))))

不太容易阅读:-)。

另外,我可能希望thisthat 成为照应并扩展到它们自己:~'this

【问题讨论】:

    标签: macros clojure


    【解决方案1】:

    (1) defprotocol 不适用于 do 形式。它不会引发错误,但也不起作用。

    (2) 你不能以这种方式做你想做的事。 defprotocol 是被调用的宏,因此对子表单的展开方式有绝对的权威。

    (3) 项目 (2) 提出了一个解决方案,实际上与您最近的一个问题相同:定义一个新宏,例如 with-methods,它采用方法名称列表,然后是其他任何内容defprotocol 参数,并扩展为已完成适当替换和拼接的 defprotocol,以便 defprotocol 可以和平扩展,而无需了解您的 do-template 技巧。

    【讨论】:

    • 谢谢。我将编写build-protocolbuild-reify 宏来创建适当的结构,每个结构都有一个类似(build-protocol name simple & complex) 的签名,其中simple 是“简单”声明((a-method [this])) 和complex 的向量是零个或多个使用~@ 插入的表单。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多