向量

Vectors也是一种有序的集合。这种集合对于从最后面删除一个元素,或者获取最后面一个元素是非常高效的(O(1))。这意味着对于向vector里面添加元素使用conj被使用cons更高效。Vector对于以索引的方式访问某个元素(用nth命令)或者修改某个元素(用assoc)来说非常的高效。函数定义的时候指定参数列表用的就是vector。

下面是两种创建vector的方法:

(def stooges (vector "Moe" "Larry" "Curly"))
(def stooges ["Moe" "Larry" "Curly"])

除非你要写的程序要特别用到list的从前面添加/删除效率很高的这个特性, 否则一般来说我们鼓励你们用vector而不是lists。这主要是因为语法上 [...] 比 ‘ (...) 更自然,更不容易弄混淆。因为函数,宏以及special form的语法也是 (...)。

get 获取vector里面指定索引的元素. 我们后面会看到get也可以从map里面获取指定key的value。索引是从0开始的。 get 函数和函数 nth 类似. 它们都接收一个可选的默认值参数 — 如果给定的索引超出边界,那么会返回这个默认值。如果没有指定默认值而索引又超出边界了, get 函数会返回 nilnth 会抛出一个异常. 看例子:

(get stooges 1 "unknown") ; -> "Larry"
(get stooges 3 "unknown") ; -> "unknown"

assoc 可以对 vectors 和 maps进行操作。 当用在 vector上的时候, 它会从给定的vector创建一个新的vector, 而指定的那个索引所对应的元素被替换掉。如果指定的这个索引等于vector里面元素的数目,那么我们会把这个元素加到新vector的最后面去;如果指定的索引比vector的大小要大,那么一个 IndexOutOfBoundsException 异常会被抛出来。看代码:

(assoc stooges 2 "Shemp") ; -> ["Moe" "Larry" "Shemp"]

subvec 获取一个给定vector的子vector。它接受三个参数,一个vectore, 一个起始索引以及一个可选的结束索引。如果结束索引没有指定,那么默认的结束索引就是vector的大小。新的vector和原来的vector共享内存(所以高效)。

所有上面的对于list的例子代码对于vector同样适用。 peekpop 函数对于vector同样适用, 只是它们操作的是vector的最后一个元素,而对于list操作的则是第一个函数。 conj 函数从一个给定的vector创建一个新的vector — 添加一个元素到新的vector的最后面去. cons 函数从一个给定的vector创建一个新的vector — 添加一个新的元素到vector的最前面去。