gpt4 book ai didi

macros - 如何避免 Clojure 中的照应宏?

转载 作者:行者123 更新时间:2023-12-03 07:05:06 29 4
gpt4 key购买 nike

以这个(简化的)示例为例:

(defmacro make [v & body]
`(let [~'nv ~(some-calc v)]
~(map #(if (= % :value) 'nv %) body)))

现在符号nv已被硬编码。有没有办法以某种方式 gensym nv 并且仍然能够在 map 函数中使用它?

顺便问一下,这实际上是一个照应宏吗?

最佳答案

答案包含在问题中:只需使用 gensym 就像 Clojure 没有 auto-gensyms 一样。

(defmacro make [v & body]
(let [value-sym (gensym)]
`(let [~value-sym ~(some-calc v)]
~@(replace {:value value-sym} body))))

请注意,我不确定您是否真的想要 ~ 还是 ~@ - 这取决于 body 是否应该是在 let 中执行的表达式序列,或单个函数调用的参数序列。但是 ~@ 会更加直观/正常,所以这就是我要猜测的。

这个宏是否是照应有点值得怀疑:肯定是将 nv 引入到调用范围中,但这基本上是无意的,所以我会说不。在我的修订版本中,我们不再引入 nv 或类似的内容,但我们“神奇地”用 v 替换 :value。不过,我们只在主体的最顶层执行此操作,因此这不像引入真正的作用域 - 我想说这更像是让客户端的代码在极端情况下意外中断。

有关这种欺骗行为如何出现的示例,假设 body 的元素之一是 (inc :value)。它不会被宏替换,并且会扩展为 (inc :value),但永远不会成功。因此,我建议使用一个真实照应宏,它引入了符号的真实范围。类似的东西

(defmacro make [v & body]
`(let [~'the-value ~(some-calc v)]
~@body))

然后调用者可以在他们的代码中使用the-value,它的行为就像一个真正的、常规的本地绑定(bind):你的宏通过魔法引入它,但它没有任何其他特殊技巧。

关于macros - 如何避免 Clojure 中的照应宏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9764377/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com