Clojure 什么是';作为前缀添加到宏中的变量时暗示
鉴于下面的宏-Clojure 什么是';作为前缀添加到宏中的变量时暗示,clojure,Clojure,鉴于下面的宏- (defmacro defhello [fn-name body] `(defn ~fn-name [~'name] ~body)) 以及在调用时定义为- (defhello问候语(str“Hello”name)) 并称为 (问候“乔”) ,将返回 你好,乔 我不明白name参数前面的~'的用法是什么?它有什么作用?不引用(')和取消引用(~)会相互取消吗?当它们一起使用时会发生什么?为什么不直接写名称而不写它们呢?据我所知,您引用了函数定义,因此在定义宏时不会对其求值。使
(defmacro defhello [fn-name body] `(defn ~fn-name [~'name] ~body))
以及在调用时定义为-
(defhello问候语(str“Hello”name))
并称为
(问候“乔”)
,将返回
你好,乔
我不明白name参数前面的~'的用法是什么?它有什么作用?不引用(')和取消引用(~)会相互取消吗?当它们一起使用时会发生什么?为什么不直接写名称而不写它们呢?据我所知,您引用了函数定义,因此在定义宏时不会对其求值。使用unquote运算符
~
,计算定义中的名称。如果名称是一种列表,~@
(unquote splice)将计算列表中没有括号的元素。简而言之,~
以语法引号形式计算表达式,就像它对~fn name
一样。在这种情况下,要计算的表达式是'name
,其中结果是非限定符号name
但是,让我们一次分解一部分
如果您只有非限定符号name
,则在运行时它将被计算为clojure.core/name
。这将导致不正确的defn
表单,并导致编译器异常
(defn greeting [clojure.core/name] (str "Hello" name))
(defn greeting [(quote clojure.core/name)] (str "Hello" name))
如果您只引用了非限定符号“name
,它仍将在运行时进行计算。区别在于它将扩展到(quote clojure.core/name)
。同样,这将导致不正确的defn
表单,并导致编译器异常
(defn greeting [clojure.core/name] (str "Hello" name))
(defn greeting [(quote clojure.core/name)] (str "Hello" name))
最后,通过使用~'name
,您将在编译时对引用的表单进行求值,从而得到不合格的符号name
,从而为您留下一个正确的defn
表单
(defn greeting [name] (str "Hello" name))
1-对于本例,这是正确的,因为它假定另一个名称
函数不存在。名称前的引号用于防止符号限定
如果您不知道什么是资格赛,请参阅
此外,还可以用于宏调试
如果你想更多地了解宏,我建议你阅读。也许有点难,但这让你知道宏是如何工作的。这个例子是从哪里来的?我写的。工作如期进行。但是~'只是反复试验,所以想知道它为什么会起作用。1)为什么它将符号计算为clojure.core/name ns,而不是当前的ns?这是所有符号解析的默认行为吗?不是。它正在评估符号
name
到clojure.core/name
,因为该函数已经存在并且在范围内。(clojure.core
默认情况下提供。)此外,单引号不限定名称空间,而语法引号限定名称空间。公共Lisp宏与clojure宏有细微的不同。