【发布时间】:2016-06-23 17:58:08
【问题描述】:
(抱歉,如果这是另一个问题的重复,我搜索所有那些花哨的特殊字符没有产生任何结果。)
我正在阅读Mastering Clojure Macros,但无法理解以下示例:
(defmacro inspect-caller-locals []
(->> (keys &env)
(map (fn [k] [`'~k k]))
(into {})))
=> #'user/inspect-caller-locals
(let [foo "bar" baz "quux"]
(inspect-caller-locals))
=> {foo "bar", baz "quux"}
下面和更简单的'k有什么区别?
`'~k
据我了解,最里面的 unquote ~ 应该只是恢复最外面的语法引用 ` 的效果,但是一个简短的实验表明它还有更多:
(defmacro inspect-caller-locals-simple []
(->> (keys &env)
(map (fn [k] ['k k]))
(into {})))
=> #'user/inspect-caller-locals-simple
(let [foo "bar" baz "quux"]
(inspect-caller-locals-simple))
CompilerException java.lang.RuntimeException: Unable to resolve symbol: k in this context, compiling:(/tmp/form-init4400591386630133028.clj:2:3)
很遗憾,我通常的调查方法在这里并不适用:
(macroexpand '(let [foo "bar" baz "quux"]
(inspect-caller-locals)))
=> (let* [foo "bar" baz "quux"] (inspect-caller-locals))
(let [foo "bar" baz "quux"]
(macroexpand '(inspect-caller-locals)))
=> {}
我在这里错过了什么?
【问题讨论】:
-
不要使用宏扩展,而是尝试评估您关心的宏部分,方法是在您的 repl 中运行:
(let [k 'foo] [k 'k `'~k])