macros - 强制扩展 Clojure 宏内的表达式

标签 macros clojure

我正在尝试使用 Stuart Sierra 的 do-template defprotocol 中的宏,并且 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 ...)) 并得到:

(do (clojure.core/seq (clojure.core/concat (clojure.core/list (symbol (str foo "-method"))) (clojure.core/list (clojure.core/apply clojure.core/vector (clojure.core/seq (clojure.core/concat (clojure.core/list (quote user/this)) (clojure.core/list (quote user/that)))))))) (clojure.core/seq (clojure.core/concat (clojure.core/list (symbol (str bar "-method"))) (clojure.core/list (clojure.core/apply clojure.core/vector (clojure.core/seq (clojure.core/concat (clojure.core/list (quote user/this)) (clojure.core/list (quote user/that)))))))) (clojure.core/seq (clojure.core/concat (clojure.core/list (symbol (str baz "-method"))) (clojure.core/list (clojure.core/apply clojure.core/vector (clojure.core/seq (clojure.core/concat (clojure.core/list (quote user/this)) (clojure.core/list (quote user/that)))))))))

不太容易阅读:-)。

此外,我可能希望 thisthat 成为 anaphora 并扩展为自身:~'this.

最佳答案

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

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

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

关于macros - 强制扩展 Clojure 宏内的表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6402316/

相关文章:

c++ - 避免 if else 打印 block 中的代码重复

c++ - 在 C++ 中使用双包含守卫

macros - 我可以通过宏中的多个规则重复匹配吗?

functional-programming - 为什么 Maybe/Option 在 Clojure 中的使用不那么普遍?

Clojure 代理问题 - 使用发送

c - 如何处理c中的结构?

javascript - ImageJ 宏路径问题

Clojure - 保存记录类型的注册表

nginx - 我可以将 Clojure 与 nginx 一起使用吗?

ide - ClojureCLR 编辑器