Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Macros 编写宏以交换两个符号的值_Macros_Clojure - Fatal编程技术网

Macros 编写宏以交换两个符号的值

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

我想不出任何可能的使用案例,但是作为一个练习,我试图写一个宏来交换分配给两个符号的值,以使我的思想更深入地围绕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))
     (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是个坏主意的事实,让我们假设你真的想这么做。你的问题有两个方面:

  • 您在
    ~tmp
    上有一个unquote,您只需要
    tmp
  • 您在
    x
    y
    上缺少一个unquote:您想
    (def~x~y)
    (def~y tmp)

您编写的版本总是分配给名为
x
y
的变量,而不是修改用户提供的变量。

提示:使用
(宏扩展-1'(交换四个五个))
查看哪里出了问题。哈哈!这就解决了问题。谢谢在一个半相关的注释中,为了使
alter var root
版本正常工作,我必须将
alter var root
行更改为,例如
(alter var root(var~x)(fn[##]~y))
。我不仅不正确地取消了中间gensym var
tmp
的引用,也没有取消
x
y
,而且我的匿名函数的算术错误。