原文: http://weibo.com/ttarticle/p/show?id=2309404017548998904747#_0
此文不详细介绍每种 Collections 到底是什么,如果要看那个请点文内每种 Collections 的 Clojure 官网链接。写这篇文实际上是因为觉得上条发过的 UML 图仍然难以查看,所以干脆用文字把平常用得多的东西写出来。Clojure 的 Collections 看上去有很多 Interface,很多 Class,一眼望过去线条错综复杂,几乎都看不到边。事实上实际用的时候也就不过那几种。下面我们分别来说明一下:
Seq (Sequence)
http://clojure.org/reference/sequences
在 Clojure里面大多数情况下 seq 如果不是 list 的话,就是 lazy 的。上面那个 Clojure 官网的链接页面底部有很详细的对于 seq 可以进行的操作介绍。如何判断这个东西是不是 Seq?简单,用 seq?
就可以了。但是注意,这不能区分 seq 和 list。用 (list 1 2 3)
和 '(1 2 3)
这种形式创造的是 PersistentList
,这仍然是一种 seq。
List: '()
http://clojure.org/reference/data_structures#Lists
List 大部分情况下都是种 seq。你可以把它理解为一种 linked list。只有一种 list 它不是 seq,那就是 empty list。怎么判断这个东西是个 list?简单,用 list?
就可以了。总体来说非空的 list 都是 seq,然而 seq 底下包含了非 list 的其他 seq,比如 lazy seq。
Vector: []
http://clojure.org/reference/data_structures#Vectors
Vector 可以基本理解为有 index 的 array。不像 list,它取第 k
个元素是 O(1)
的。怎么判断这个东西是个 vector?用vector?
。请注意,vector 不像 list,它不是 seq。
List 跟 Vector 都是有序的(就是会存储加入元素早晚的顺序),如果想查这个 collection 是不是有序的,怎么办?用 sequential?
。这种属性在 Clojure 里面是用一个叫 Sequential
的 Interface 实现的。List,Vector 和常用的 Seq 类型(比如Lazy seq)都在这个范围内。
Map: {}
http://clojure.org/reference/data_structures#Maps
基本概念就像 Java 里面的 Map。可以用 map?
判断一个东西是不是 map。
Associative
Vector 和 Map 同属这个种类。Vector 存有 index 到 value 的 association。Map 存有 key 到 value 的 association。如果要测试一个东西是不是存有这种关联属性,用 associative?
。在 Clojure 里面,Vector 和 Map 都可以作为函数直接针对index/key 取值。比如:
([1 2 3] 1) -> 2
意为取 index 为 1
的数,即第二个数。在 [1 2 3]
这个 vector 里面,第二个数是 2
。
({:a 1 :b 2} :a) -> 1
意为取 :a
对应的值。在 {:a 1 :b 2}
这个 map 里面,:a
对应的值是 1
。
Set: #{}
基本概念就像 Java 里面的 Set。可以用 set?
判断一个东西是不是 set。
sorted(即排序的,这和存留元素加入顺序的 sequential 不同,这是按 comparator 排序)
Clojure 里有 TreeSet 和 TreeMap,各自都是在加入新元素时可以自动保持值的顺序。它们可以分别用 sorted-set
和 sorted-map
进行创建。如果想知道一个东西是不是 sorted,可以用 sorted?
。
总结
判断是不是 seq:用 seq?
判断是不是 list:用 list?
判断是不是 map:用 map?
判断是不是 set:用 set?
判断是不是 map 或者 vector:用 associative?
判断是不是 seq 或者 list 或者 vector(即有序吗):用 sequential?
判断是不是自动排序的(即 sorted set 或者 sorted map):用 sorted?
常用的就是这些。很有可能我漏掉了什么别的常用的东西,大家可以补充。