Clojure:宏中的错误."没有这样的变化"

tun*_*ten 2 lisp macros clojure

当我在clojure中使用宏时,我遇到了问题.这就是我想要做的.

(defmacro working-example []
  '(+ foo 1))

(defn working-function [foo]
  (working-example))

(working-function 2) ; => 3

(defmacro broken-example [bar]
  `(+ foo ~bar))

(defn broken-function [foo]
  (broken-example 1)) ; => I get error here.

(broken-function 2) ; Should be 3.
Run Code Online (Sandbox Code Playgroud)

我希望破碎的示例宏只替换文本,就像工作示例一样.为什么它不起作用,我应该如何使它工作?

Die*_*lla 5

我对Clojure很新,但我会试着解释一下这里发生了什么.引用和反引用在处理符号方面有所不同.例如,您可以编写类似的代码,导致细微的差异:

user=> '(+ foo 2)
(+ foo 2)
user=> `(+ foo 2)
(clojure.core/+ user/foo 2)
Run Code Online (Sandbox Code Playgroud)

注意如何使用反引号将符号"绑定"到相应的命名空间(clojure.corefor +userfor foo).相反,引用只是将符号视为原样.如果要正确编写损坏的函数,可以使用以下list语法:

(defmacro broken-example [bar]
  (list '+ 'foo bar))

(defn broken-function [foo]
  (broken-example 1))

(broken-function 2)
Run Code Online (Sandbox Code Playgroud)

现在broken-function输出预期结果.

编辑:

现在感谢下面的A. Webb评论,您还可以使用以下语法来避免命名空间绑定:

(defmacro broken-example [bar]
  `(+ ~'foo ~bar))
Run Code Online (Sandbox Code Playgroud)

  • “我知道有一种方法可以防止反引号在命名空间中查找符号” –`\`(+〜'foo 2)` (2认同)