如何在Clojure宏中捕获词法范围?

Dun*_*yne 6 scope clojure

在Common Lisp中,我可以定义和使用从词法范围捕获变量的宏,以便我可以在let表单中使用它:

CL-USER> (defmacro plus9 () `(+ 9 woo))
PLUS9
CL-USER> (macroexpand '(plus9))
(+ 9 WOO)
T
CL-USER> (let ((woo 1)) (plus9))
10
Run Code Online (Sandbox Code Playgroud)

然而,当我定义Clojure中的一个类似的宏,它寻找的定义woouser命名空间:

user=> (defmacro plus9 [] `(+ 9 woo))
#'user/plus9
user=> (macroexpand '(plus9))
(clojure.core/+ 9 user/woo)
user=> (let [woo 1] (plus9))

CompilerException java.lang.RuntimeException: No such var: user/woo
Run Code Online (Sandbox Code Playgroud)

显然,我误解了范围在Clojure中的工作原理.用Clojure实现这个宏的正确方法是什么?

slo*_*oth 8

我是一个宏菜鸟,但是怎么样

user=> (defmacro plus9 [] `(+ 9 ~'woo))
#'user/plus9
user=> (macroexpand '(plus9))
(clojure.core/+ 9 woo)
user=> (let [woo 1] (plus9))
10
Run Code Online (Sandbox Code Playgroud)

  • 是啊.这就是你如何捕获clojure中的词法绑定.syntax-quote将根据命名空间限定符号,从而确保卫生.出于这个原因,`〜'`被认为是代码气味并且惯用,你将要捕获的符号传递给宏:```(defmacro plus9 [sym]`(+ 9~sym)),(让[x 1](加9 x))``` (4认同)