clojure.core:。运算符、defmacro和setMacro

clojure.core:。运算符、defmacro和setMacro,clojure,function,Clojure,Function,在查看defmacro定义后的clojure.core文件时,您会看到以下代码: (. (var defmacro) (setMacro)) 这意味着什么?我将把整行内容分解,因为我不知道你已经知道了什么 首先,报告说: 符号必须解析为var,并且返回var对象本身(而不是其值) 如果我们在REPL中键入此项,我们会得到: user=> (var defmarco) #'clojure.core/defmacro 现在,特殊表单允许您执行以下操作。在这种情况下,将调用返回的Var对象上

在查看
defmacro
定义后的clojure.core文件时,您会看到以下代码:

(. (var defmacro) (setMacro))

这意味着什么?我将把整行内容分解,因为我不知道你已经知道了什么

首先,报告说:

符号必须解析为var,并且返回var对象本身(而不是其值)

如果我们在REPL中键入此项,我们会得到:

user=> (var defmarco)
#'clojure.core/defmacro
现在,
特殊表单允许您执行以下操作。在这种情况下,将调用返回的
Var
对象上的

我对代码不太熟悉,无法真正理解
setMacro
在做什么,但我认为它正在改变变量的状态,以表示它是一个宏,而不是一个函数或其他东西。

(.foo(bar))是(.bar-foo)的低级等价物,因此,这在defmacro变量上调用方法setMacro,而不带任何参数


我怀疑这个调用将defmacro函数/var标记为一个宏。一般来说,clojure.core中的很多东西都使用低级技巧来引导语言,因此,虽然了解东西是如何构建的很有趣,但它并不是一个好的惯用代码源。

Joost和Jeremy的回答解释了
的含义。如果您想知道此特定方法调用实现的细节:

这基本上是在名为
clojure.core/defmacro
的变量的元数据映射中插入一个名为
:macro
的键,该键的值为
true
。这样做的效果是,从这一点开始,如果编译器在其解析为var
#clojure.core/defmacro
的上下文中遇到符号
defmacro
#'foo
(var foo)
)的简写,这通常无处不在,尽管您可以使用
let
绑定的局部变量对该变量进行阴影处理,但它会知道,对于宏的名称,它应该适当地处理该变量

(也就是说,(1)如果符号
defmacro
出现在运算符位置,即在打开参数的右侧,则使用绑定到
#'clojure.core/defmacro
的函数展开宏调用,或者抛出异常以抱怨在非运算符位置提到宏名称。)


顺便说一句,Clojure编译器通常在变量上使用这种元数据映射,例如决定各种对象的类型(参见
:tag
元数据)或是否内联函数调用(IIRC,
:inline
:inline arities
)。

以不同的方式陈述第二段,如果您发现自己需要在自己的代码中调用(.setMacro),那么几乎可以肯定您错了。