Macros 编写宏以交换两个符号的值
我想不出任何可能的使用案例,但是作为一个练习,我试图写一个宏来交换分配给两个符号的值,以使我的思想更深入地围绕Clojure的宏 以下是我尝试过的两件事: 方法1:Macros 编写宏以交换两个符号的值,macros,clojure,Macros,Clojure,我想不出任何可能的使用案例,但是作为一个练习,我试图写一个宏来交换分配给两个符号的值,以使我的思想更深入地围绕Clojure的宏 以下是我尝试过的两件事: 方法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)) (alt
(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:无法解析符号:tmp 35;在这个上下文中
。我是否错误地使用了auto gensym
使用方法1,我可以通过将最后一行更改为
(def y tmp#))
(在tmp#
之前取出~
)来运行它,但是我得到的输出是未交换的four:4\nfive:5
忽略这样突变vars是个坏主意的事实,让我们假设你真的想这么做。你的问题有两个方面:
- 您在
上有一个unquote,您只需要~tmp
tmp
- 您在
和x
上缺少一个unquote:您想y
和(def~x~y)
(def~y tmp)
您编写的版本总是分配给名为
x
和y
的变量,而不是修改用户提供的变量。提示:使用(宏扩展-1'(交换四个五个))
查看哪里出了问题。哈哈!这就解决了问题。谢谢在一个半相关的注释中,为了使alter var root
版本正常工作,我必须将alter var root
行更改为,例如(alter var root(var~x)(fn[##]~y))
。我不仅不正确地取消了中间gensym vartmp
的引用,也没有取消x
和y
,而且我的匿名函数的算术错误。