当在宏中添加为变量的前缀时,它意味着什么呢?

时间:2012-09-10 12:44:26

标签: clojure

鉴于下面的宏 -

(defmacro defhello [fn-name body]   `(defn ~fn-name [~'name] ~body))

和被称为 -

时定义的函数
  

(defhello greeting(str“你好”的名字))

并称为

  

(问候“乔”)

,将返回

Hello Joe

我不明白 name 参数前面的〜'的用法?它有什么作用?不引用(')和取消引用(〜)相互取消?当它们一起使用时会发生什么?为什么不在没有它们的情况下编写 name

3 个答案:

答案 0 :(得分:9)

简而言之,~评估语法引用表单中的表达式,就像它对~fn-name一样。在这种情况下,要评估的表达式为'name,其中结果为非限定符号name

然而,让我们一次打破这个。

如果您只有非限定符号name,则会在运行时 1 对其进行评估clojure.core/name。这将导致不正确的defn形式并导致编译器异常。

(defn greeting [clojure.core/name] (str "Hello" name)) 

如果您只有引用的非限定符号'name,它仍将在运行时进行评估。不同之处在于它会扩展到(quote clojure.core/name)。同样,这会导致不正确的defn形式并导致编译器异常。

(defn greeting [(quote clojure.core/name)] (str "Hello" name))

最后,通过使用~'name,您将在编译时评估引用的表单,从而生成不合格的符号name,为您留下正确的defn表单。

(defn greeting [name] (str "Hello" name))

1 - 这个例子的确如此,因为它假定另一个name函数不存在。

答案 1 :(得分:2)

据我了解,您引用函数定义,因此在定义宏时不会对其进行求值。您可以使用非引号运算符~来计算定义中的名称。如果name是一种列表~@(unquote splice)将评估列表的元素而不包含周围的括号。

答案 2 :(得分:1)

name 之前的引号用于保持符号符合条件。

如果您不知道排位赛的内容,请参阅Reader

此外,您可以使用macroexpand进行宏调试。

如果您想了解有关宏的更多信息,建议您阅读On Lisp。也许这有点困难,但是让你知道宏是如何运作的。