A list is denoted by parentheses:
()
;;=> ()
A Clojure list is a singly linked list. conj
"conjoins" a new element to the collection in the most efficient location. For lists, this is at the beginning:
(conj () :foo)
;;=> (:foo)
(conj (conj () :bar) :foo)
;;=> (:foo :bar)
Unlike other collections, non-empty lists are evaluated as calls to special forms, macros, or functions when evaluated. Therefore, while (:foo)
is the literal representation of the list containing :foo
as its only item, evaluating (:foo)
in a REPL will cause an IllegalArgumentException
to be thrown because a keyword cannot be invoked as a nullary function.
(:foo)
;; java.lang.IllegalArgumentException: Wrong number of args passed to keyword: :foo
To prevent Clojure from evaluating a non-empty list, you can quote
it:
'(:foo)
;;=> (:foo)
'(:foo :bar)
;;=> (:foo :bar)
Unfortunately, this causes the elements to not be evaluated:
(+ 1 1)
;;=> 2
'(1 (+ 1 1) 3)
;;=> (1 (+ 1 1) 3)
For this reason, you'll usually want to use list
, a variadic function that evaluates all of its arguments and uses those results to construct a list:
(list)
;;=> ()
(list :foo)
;;=> (:foo)
(list :foo :bar)
;;=> (:foo :bar)
(list 1 (+ 1 1) 3)
;;=> (1 2 3)
count
returns the number of items, in constant time:
(count ())
;;=> 0
(count (conj () :foo))
;;=> 1
(count '(:foo :bar))
;;=> 2
You can test whether something is a list using the list?
predicate:
(list? ())
;;=> true
(list? '(:foo :bar))
;;=> true
(list? nil)
;;=> false
(list? 42)
;;=> false
(list? :foo)
;;=> false
You can get the first element of a list using peek
:
(peek ())
;;=> nil
(peek '(:foo))
;;=> :foo
(peek '(:foo :bar))
;;=> :foo
You can get a new list without the first element using pop
:
(pop '(:foo))
;;=> ()
(pop '(:foo :bar))
;;=> (:bar)
Note that if you try to pop
an empty list, you'll get an IllegalStateException
:
(pop ())
;; java.lang.IllegalStateException: Can't pop empty list
Finally, all lists are sequences, so you can do everything with a list that you can do with any other sequence. Indeed, with the exception of the empty list, calling seq
on a list returns the exact same object:
(seq ())
;;=> nil
(seq '(:foo))
;;=> (:foo)
(seq '(:foo :bar))
;;=> (:foo :bar)
(let [x '(:foo :bar)]
(identical? x (seq x)))
;;=> true