清单
列表用括号表示:
()
;;=> ()
Clojure 列表是单链表 。conj
联合一个新元素到最高效的位置集合。对于列表,这是在开头:
(conj () :foo)
;;=> (:foo)
(conj (conj () :bar) :foo)
;;=> (:foo :bar)
与其他集合不同,非空列表在评估时被评估为对特殊表单,宏或函数的调用。因此,虽然 (:foo)
是包含:foo
作为其唯一项目的列表的文字表示,但是在 REPL 中评估 (:foo)
将导致 IllegalArgumentException
被抛出,因为关键字不能被调用为 nullary 函数 。
(:foo)
;; java.lang.IllegalArgumentException: Wrong number of args passed to keyword: :foo
为了防止 Clojure 评估非空列表,你可以知道它:
'(:foo)
;;=> (:foo)
'(:foo :bar)
;;=> (:foo :bar)
不幸的是,这会导致不评估元素:
(+ 1 1)
;;=> 2
'(1 (+ 1 1) 3)
;;=> (1 (+ 1 1) 3)
出于这个原因,你通常希望使用 list
,一个可变参数函数 ,用于计算其所有参数并使用这些结果构造一个列表:
(list)
;;=> ()
(list :foo)
;;=> (:foo)
(list :foo :bar)
;;=> (:foo :bar)
(list 1 (+ 1 1) 3)
;;=> (1 2 3)
count
以恒定时间返回项目数:
(count ())
;;=> 0
(count (conj () :foo))
;;=> 1
(count '(:foo :bar))
;;=> 2
你可以使用 list?
谓词测试某些内容是否为列表 :
(list? ())
;;=> true
(list? '(:foo :bar))
;;=> true
(list? nil)
;;=> false
(list? 42)
;;=> false
(list? :foo)
;;=> false
你可以使用 peek
获取列表的第一个元素 :
(peek ())
;;=> nil
(peek '(:foo))
;;=> :foo
(peek '(:foo :bar))
;;=> :foo
你可以使用 pop
获取没有第一个元素的新列表 :
(pop '(:foo))
;;=> ()
(pop '(:foo :bar))
;;=> (:bar)
请注意,如果你尝试将空列表清空,你将得到一个 IllegalStateException
:
(pop ())
;; java.lang.IllegalStateException: Can't pop empty list
最后,所有列表都是序列,因此你可以使用可以对任何其他序列执行的列表执行所有操作。实际上,除了空列表之外,在列表上调用 seq
会返回完全相同的对象:
(seq ())
;;=> nil
(seq '(:foo))
;;=> (:foo)
(seq '(:foo :bar))
;;=> (:foo :bar)
(let [x '(:foo :bar)]
(identical? x (seq x)))
;;=> true