我无法想到任何可能的用例,但作为一种练习,试图围绕Clojure的宏进一步思考,我正在尝试编写一个宏来交换分配给两个符号的值。 / p>
我尝试了两件事:
方法1:
(defmacro swap [x y]
`(let [tmp# ~x]
(def x ~y)
(def y ~tmp#)))
方法2:
(defmacro swap [x y]
`(let [tmp# ~x]
(alter-var-root #'x (fn [] ~y))
(alter-var-root #'y (fn [] ~tmp#))))
以下是我用来测试它的代码:
(def four 4)
(def five 5)
(swap four five)
(printf "four: %d\nfive: %d" four five)
预期产出:
four: 5
five: 4
但是,使用任一版本的宏,我得到java.lang.RuntimeException: Unable to resolve symbol: tmp# in this context
。我使用auto gensym不正确吗?
使用方法1,我可以通过将最后一行更改为(def y tmp#)))
(在~
之前取出tmp#
)来运行它,但是我得到了输出{{ 1}}没有交换。
答案 0 :(得分:3)
忽略像这样改变vars的事实是一个坏主意,让我们假设你真的想要这样做。你的问题有两个方面:
~tmp#
上有一个取消引用,只需要tmp#
x
和y
上的取消引用:您想要(def ~x ~y)
和(def ~y tmp#)
您编写的版本始终会分配给名为x
和y
的变种,而不是修改用户提供的变量。