清单

列表用括号表示:

()
;;=> ()

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