【发布时间】:2011-06-08 01:32:44
【问题描述】:
Clojure 元数据仅在函数谨慎执行且 Clojure 核心函数未全局保留元数据时才会保留。我听说的一般经验法则是,conj、assoc 等集合函数应该保留 meta,但 map、filter、take 等序列函数不保留 meta。
在某处有哪些功能可以保留元数据的列表吗?
【问题讨论】:
Clojure 元数据仅在函数谨慎执行且 Clojure 核心函数未全局保留元数据时才会保留。我听说的一般经验法则是,conj、assoc 等集合函数应该保留 meta,但 map、filter、take 等序列函数不保留 meta。
在某处有哪些功能可以保留元数据的列表吗?
【问题讨论】:
这都是关于类型的。序列函数的行为就像他们在参数上调用 seq 一样,因此并不总是返回相同类型的对象。集合函数和特定类型的函数不会调用 seq 并返回与给定它们的类型相同的对象。这有点让他们产生返回相同对象的错觉(这可能是这种行为的原因),即使事实并非如此。我们可以说经验法则是函数在保留类型的同时保留元数据。
user> (meta (seq (with-meta (list 1) {:a 1})))
{:a 1}
user> (meta (seq (with-meta (vector 1) {:a 1})))
nil
一定要注意什么时候涉及懒惰:
user> (type (list 1))
clojure.lang.PersistentList
user> (type (map identity (list 1)))
clojure.lang.LazySeq
user> (meta (seq (with-meta (map identity (list 1)) {:a 1})))
nil
有关在收集时保留元数据的函数列表,请参阅data structures 页面。不保留元数据的位于sequences 页面下,但它们返回相同类型的对象时除外。
在幕后我不太确定细节,因为添加了惰性和分块序列,但您可以查看 RT 类中的 cons、seq 和 seqFrom 方法。不保留元数据的功能通过这些方法。而集合函数最终会使用特定于其类型的方法。
【讨论】: