【问题标题】:`def` vs `declare` for forward declaration`def` vs `declare` 用于前向声明
【发布时间】:2015-11-22 14:14:00
【问题描述】:

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

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

【问题讨论】:

    标签: clojure forward-declaration


    【解决方案1】:

    declaredef 都会创建一个未绑定的 var,但使用 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)))
    

    【讨论】:

      【解决方案2】:

      文档给出了答案:

      => (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 的优点是为以后的读者显示意图。 (declare x y z) 表示我打算对这些符号进行前向声明,因为宏是 useful for making forward declarations.

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

      因此,在进行前向声明时,(declare x) 应该优先于 (def x),以便对代码的未来读者表示怜悯。

      【讨论】:

        【解决方案3】:

        def 始终适用于根绑定,即使 var 在调用 def 时是线程绑定的。

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-10-16
          • 1970-01-01
          • 2021-01-16
          • 1970-01-01
          相关资源
          最近更新 更多