【问题标题】:Clojure: Error in macro. "No such var"Clojure:宏中的错误。 “没有这样的变量”
【发布时间】:2014-01-13 15:46:00
【问题描述】:

我在 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.

我希望损坏的示例宏只替换文本,就像工作示例一样。为什么它不起作用,我应该如何让它起作用?

【问题讨论】:

    标签: macros clojure lisp


    【解决方案1】:

    我对 Clojure 还很陌生,但我会尝试向您解释这里发生了什么。引用和反引用在处理符号的方式上是不同的。例如,您可以编写导致细微差别的类似代码:

    user=> '(+ foo 2)
    (+ foo 2)
    user=> `(+ foo 2)
    (clojure.core/+ user/foo 2)
    

    注意如何使用反引号将符号“绑定”到相应的命名空间(clojure.core 对应于+user 对应于foo)。相反,引用只是按原样处理符号。如果您想正确编写损坏的函数,可以使用list 语法:

    (defmacro broken-example [bar]
      (list '+ 'foo bar))
    
    (defn broken-function [foo]
      (broken-example 1))
    
    (broken-function 2)
    

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

    编辑

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

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

    【讨论】:

    • "我知道有一种方法可以防止反引号在命名空间中查找符号" -- `(+ ~'foo 2)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-10
    • 2012-08-19
    相关资源
    最近更新 更多