`def`和`declare`用于前向声明,它们有什么区别?

23

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

什么情况下应该使用 (declare x) 而不是 (def x)

3个回答

26

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

  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)))

6
文档已经给出了答案:
=> (doc declare)
-------------------------
clojure.core/declare
([& names])
Macro
  defs the supplied var names with no bindings, useful for making forward declarations.
从实现上看,很明显declare是基于def定义的,并提供了一点语法糖。所以从功能上来说,它们几乎是一样的。 declare的优势在于向后读者展示意图。 (declare x y z)表示我打算提前声明这些符号,因为该宏“可用于进行前向声明”。 (def x) (def y) (def z)表示我正在将这些符号加入到命名空间中,但您不知道我是否打算为它们提供定义并忘记了,还是我正在做前向声明,或者可能是其他微妙的事情。
因此,在进行前向声明时应首选(declare x)而不是(def x),以便对代码未来读者有所帮助。

1

def总是应用于根绑定,即使在调用def时变量在线程中绑定。

def返回变量本身(而不是其值)。如果符号已经存在于命名空间中并且未映射到一个内部变量,则会抛出异常。

使用没有绑定的提供的变量名称声明def,有助于进行前向声明。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接