Clojure,有一个declare
宏,允许你转发声明函数或变量。它似乎与def
完全相同:(declare x)
和(def x)
都创建了#<Unbound Unbound: #'user/x>
什么时候应该使用(declare x)
代替(def x)
?
答案 0 :(得分:18)
declare
和def
都会创建一个未绑定的var,但使用declare
有三个好处:
(declare x y z)
{:declared true}
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)))
答案 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名称,对于进行前向声明很有用。