`def` vs`declare`用于前向声明

时间:2015-11-22 14:14:01

标签: clojure forward-declaration

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

什么时候应该使用(declare x)代替(def x)

3 个答案:

答案 0 :(得分:18)

declaredef都会创建一个未绑定的var,但使用declare有三个好处:

  1. 您可以在一个语句中创建多个变量,例如(declare x y z)
  2. vars标有附加元数据{:declared true}
  3. 使用declare这个词可以说是更清晰和惯用的
  4. (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)))
    

答案 1 :(得分:3)

文档给出了答案:

=> (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)进行前瞻性声明,以表示对未来读者代码的怜悯。

答案 2 :(得分:1)

public class ParseMyDateItemList { public static void ParseString() { string x = "[{\"Name\":\"property1\",\"Value\":true},{\"Name\":\"FOO\",\"Value\":\"12345ddddeeee\"},{\"Name\":\"property3\",\"Value\":false}]"; var dataItems = Newtonsoft.Json.JsonConvert.DeserializeObject<IList<MyDataItem>>(x); var resultDataItems = dataItems.Except(dataItems.Where(t => t.Name.ToLower() == "foo")).ToList(); var resultJson = Newtonsoft.Json.JsonConvert.SerializeObject(resultDataItems); } } public class MyDataItem { public string Name { get; set; } public object Value { get; set; } } 始终适用于根绑定,即使var在调用def的点处是线程绑定的。

def产生var本身(不是它的值)。如果符号已在命名空间中并且未映射到实例变量

,则引发异常

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