【发布时间】:2015-01-20 08:40:08
【问题描述】:
我正在尝试编写一个将 clojure 关键字转换为 java 枚举的 clojure 宏。但是宏中参数的求值比较混乱:
user=> (defmacro show-and-tell [thing]
#_=> `(vector ~(name thing) ~(type thing) ~thing))
#'user/show-and-tell
user=> (macroexpand-1 (show-and-tell :foo))
["foo" clojure.lang.Keyword :foo]
user=> (def foo :bar)
#'user/foo
user=> (name foo)
"bar"
user=> (type foo)
clojure.lang.Keyword
user=> (macroexpand-1 (show-and-tell foo))
["foo" clojure.lang.Symbol :bar]
因此,如果将关键字直接作为参数提供,它会按我的预期工作。但如果它是一个 var,我不会得到正确的 name 和 type。
我可以通过使用 eval 使其“几乎”工作:
user=> (defmacro show-and-tell-with-eval [thing]
#_=> `(vector ~(name (eval thing)) ~(type (eval thing)) ~(eval thing)))
#'user/show-and-tell-with-eval
user=> (macroexpand-1 '(show-and-tell-with-eval foo))
(clojure.core/vector "bar" clojure.lang.Keyword :bar)
user=> (let [baz :bar-foo] (macroexpand-1 '(show-and-tell baz)))
(clojure.core/vector "baz" clojure.lang.Symbol baz)
user=> (let [baz :bar-foo] (macroexpand-1 '(show-and-tell-with-eval baz)))
CompilerException java.lang.RuntimeException: Unable to resolve symbol: baz in this context
谁能给我解释一下?有没有办法在宏中看到(本地)变量的name?
【问题讨论】: