本书中有一个例子(P252),关于宏中的& env,我只是不明白如何得到结果{x 1, y 2}
(defmacro spy-env []
(let [ks (keys &env)]
`(prn (zipmap '~ks [~@ks]))))
(let [x 1 y 2]
(spy-env)
(+ x y))
; {x 1, y 2}
;= 3
我在REPL中试过这样:
user=> (defmacro spy-env [] (let [ks (keys &env)] `(prn ~@(keys &env))))
#'user/spy-env
user=> (let [x 1 y 2] (spy-env))
2 1
这是错的。
答案 0 :(得分:1)
a)如果您尝试书的代码,它会输出正确的值
user=> (defmacro spy-env []
#_=> (let [ks (keys &env)]
#_=> `(prn (zipmap '~ks [~@ks]))))
#'user/spy-env
user=> (let [x 1 y 2] (spy-env))
{x 1, y 2}
nil
user=> (let [x 1 y 2]
#_=> (spy-env)
#_=> (+ x y))
{x 1, y 2}
3
b)现在你的代码不同了
初始代码:
`(prn (zipmap '~ks [~@ks]))
VS
`(prn ~@(keys &env))
实际上@(keys& env)等于@ks
答案 1 :(得分:1)
扩展宏将是一种很好的方式,让您了解它是如何工作的,但不幸的是macroexpand-1
没有传达&env
的正确绑定。这个例子:
(let [x 1 y 2] (spy-env))
实际上扩展为:
(let [x 1 y 2] (prn (zipmap '(x y) [x y])))
你知道了吗?在第一个序列中,x
和y
未被评估,但在第二个序列中,它们是。所以它将符号拉到他们评价的任何东西。在let
块中,(zipmap '(x y) [x y])
评估为{x 1 y 2}
。