作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
以这个(简化的)示例为例:
(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/
我是一名优秀的程序员,十分优秀!