如何解释书中的&amp; env示例<clojure programming =“”> </clojure>

时间:2013-11-28 07:51:58

标签: clojure

本书中有一个例子(P252),关于宏中的&amp; 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

这是错的。

2 个答案:

答案 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&amp; 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])))
你知道了吗?在第一个序列中,xy未被评估,但在第二个序列中,它们是。所以它将符号拉到他们评价的任何东西。在let块中,(zipmap '(x y) [x y])评估为{x 1 y 2}