【问题标题】:How to explain the &env example in book <Clojure Programming>如何解释<Clojure Programming>一书中的&env例子
【发布时间】:2013-11-28 07:51:57
【问题描述】:

书里有一个例子(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

写好了。

【问题讨论】:

    标签: clojure


    【解决方案1】:

    扩展宏将是您了解它如何工作的好方法,但不幸的是macroexpand-1 没有传达&amp;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}

    【讨论】:

    • 我认为 &env 是这样的 {x 1 y 2},所以 (keys &env) 是 (x y),x 和 y 绑定到 1 和 2。所以 [~@ks] 只是[x y]([1 2])。对吗?
    【解决方案2】:

    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]))
    

        `(prn ~@(keys &env))
    

    实际上@(keys &env) 等于@ks

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-26
      • 1970-01-01
      • 2019-10-11
      相关资源
      最近更新 更多