`def` vs `declare` 前向声明

`def` vs `declare` for forward declaration

Clojure 有一个 declare 宏,允许您前向声明函数或变量。它的功能似乎与 def 完全相同:(declare x)(def x) 都创建 #<Unbound Unbound: #'user/x>

什么时候应该使用 (declare x) 而不是 (def x)

declaredef 都会创建一个未绑定的变量,但是使用 declare 有 3 个优点:

  1. 您可以在一条语句中创建多个变量,例如(declare x y z)
  2. 使用附加元数据标记变量 {:declared true}
  3. 使用 declare 这个词可以说更加清晰和地道

(source declare):

(defmacro declare
  "defs the supplied var names with no bindings, useful for making forward declarations."
  {:added "1.0"}
  [& names] `(do ~@(map #(list 'def (vary-meta % assoc :declared true)) names)))

文档给出了答案:

=> (doc declare)
-------------------------
clojure.core/declare
([& names])
Macro
  defs the supplied var names with no bindings, useful for making forward declarations.

Looking at the implementation,显然 declare 是根据 def 定义的,并提供了一点语法糖。所以在功能上,它们几乎相同。

declare 的优点是表明以后 reader 的意图。 (declare x y z) 意味着我打算对这些符号进行前向声明,因为宏是 useful for making forward declarations.

(def x) (def y) (def z) 表示我正在保留这些符号,但您不知道我是否打算给它们定义但忘记了,或者我是否在进行前向声明,或者可能是其他微妙的东西。

因此,当您进行前向声明时,(declare x) 应该比 (def x) 更受欢迎,以便对您的代码的未来 reader 表示怜悯。

def 始终适用于根绑定,即使在调用 def 时 var 为 thread-bound。

def 产生 var 本身(不是它的值)。如果符号已经在命名空间中并且未映射到内部变量,则抛出异常。

声明 def 提供的不带绑定的 var 名称,对于进行前向声明很有用。