强制扩展 Clojure 宏内的表达式

发布于 2024-11-16 12:29:43 字数 1981 浏览 5 评论 0原文

我正在尝试使用 Stuart Sierra 的 do-templatedefprotocol 中的 a> 宏,并且 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-expression 被传递给 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/应用 clojure.core/向量(clojure.core/seq (clojure.core/concat (clojure.core/list(引用用户/this)) (clojure.core/list(引用 用户/那个))))))))(clojure.core/seq (clojure.core/concat (clojure.core/list(符号(str 条 “-方法”)))(clojure.core/list (clojure.core/应用 clojure.core/向量(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/应用 clojure.core/向量(clojure.core/seq (clojure.core/concat (clojure.core/list(引用用户/this)) (clojure.core/list(引用 用户/那个)))))))))

不太容易阅读:-)。

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

I am trying to use Stuart Sierra's do-template macro inside a defprotocol and the Clojure compiler complains that I am redefining do-template -- not what I intend:

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

This should expand to:

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

The problem (I believe) is that the do-template s-expression is getting passed to defprotocol unexpanded. Is there any way to cause it to evaluate before being passed?

BTW, do-template should actually expand to

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

but I already tried that (with a hand-expanded version) and defprotocol is fine with the nested do.

How can I see the actual expansion of the do-template? I tried both (macroexpand '(do-template ...)) and (macroexpand-1 '(do-template ...)) and got:

(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)))))))))

Not exactly easy to read :-).

Also, I probably want the this and that to be anaphora and expand to themselves: ~'this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

紫轩蝶泪 2024-11-23 12:29:43

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

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

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

(1) defprotocol is not fine with a do form. It doesn't raise an error, but it doesn't work either.

(2) You can't do what you want in this way. defprotocol is the macro being called, so it has absolute authority about how sub-forms are expanded.

(3) Item (2) suggests a solution, in fact the same one as at least one of your recent questions: define a new macro, say with-methods, that takes a list of method names, followed by whatever other defprotocol arguments, and expands into a defprotocol with the appropriate substitutions and splicing already done, so that defprotocol can expand in peace without needing to know anything about your do-template trick.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文