计数
Clojure 集合将值“收集”到复合值中。有四种主要的 Clojure 集合类型:向量、列表、集合和映射。在这四种集合类型中,向量和列表是有序的。
向量是一种索引的、顺序的数据结构。向量用 [ ] 表示,如下所示
[ ]
[1 2 3]
“索引”意味着可以使用索引检索向量的元素。在 Clojure 中(与 Java 一样),索引从 0 开始,而不是 1。使用 get 函数检索指定索引处的元素
get
user=> (get ["abc" false 99] 0) "abc" user=> (get ["abc" false 99] 1) false
如果使用无效索引调用 get,则返回 nil
nil
user=> (get ["abc" false 99] 14) nil
count
所有 Clojure 集合都可以进行计数
user=> (count [1 2 3]) 3
除了文字 [ ] 语法之外,Clojure 向量还可以使用 vector 函数创建
vector
user=> (vector 1 2 3) [1 2 3]
元素使用 conj(连接的缩写)添加到向量中。元素始终添加到向量的末尾
conj
user=> (conj [1 2 3] 4 5 6) [1 2 3 4 5 6]
Clojure 集合与字符串和数字等简单值共享重要的特性,例如不可变性和按值比较相等性。
例如,让我们创建一个向量并使用 conj 对其进行修改。
user=> (def v [1 2 3]) #'user/v user=> (conj v 4 5 6) [1 2 3 4 5 6]
这里 conj 返回了一个新向量,但如果我们检查原始向量,我们会发现它没有改变
user=> v [1 2 3]
任何“更改”集合的函数都会返回一个新实例。您的程序需要记住或传递更改后的实例才能利用它。
列表是顺序的链表,它们将新元素添加到列表的头部,而不是像向量一样添加到尾部。
因为列表通过将第一个元素作为函数来调用进行评估,所以我们必须引用列表以防止评估
(def cards '(10 :ace :jack 9))
列表没有索引,因此必须使用 first 和 rest 来遍历它们。
first
rest
user=> (first cards) 10 user=> (rest cards) '(:ace :jack 9)
conj 可用于向列表添加元素,就像对向量一样。但是,conj 始终在可以对数据结构进行恒定时间操作的地方添加元素。对于列表,元素被添加到前面
user=> (conj cards :queen) (:queen 10 :ace :jack 9)
列表也可以用作带有 peek 和 pop 的栈
user=> (def stack '(:a :b)) #'user/stack user=> (peek stack) :a user=> (pop stack) (:b)