Takes any nested combination of sequential things (lists, vectors,
etc.) and returns their contents as a single, flat sequence.
(flatten nil) returns nil.
user=> (flatten [1 [2 3]])
(1 2 3)
user=> (flatten '(1 2 3))
(1 2 3)
user=> (flatten '(1 2 [3 (4 5)]))
(1 2 3 4 5)
user=> (flatten nil)
()
; Attention with stuff which is not a sequence
user=> (flatten 5)
()
user=> (flatten {:name "Hubert" :age 23})
()
; Workaround for maps
user=> (flatten (seq {:name "Hubert" :age 23}))
(:name "Hubert" :age 23)
(defn flatten
"Takes any nested combination of sequential things (lists, vectors,
etc.) and returns their contents as a single, flat sequence.
(flatten nil) returns nil."
{:added "1.2"
:static true}
[x]
(filter (complement sequential?)
(rest (tree-seq sequential? seq x))))
Comments top
3 comment(s) for flatten.
(flatten nil) actually returns an empty sequence, not nil. The doc string is fixed in 1.4.
As shown in the example, flatten will return an empty sequence when given any non-sequential thing. That can sometimes hide a bug.
Here's another version that doesn't have that problem, and is faster as well.
(defn flatten2 "Like `clojure.core/flatten` but better, stronger, faster. Takes any nested combination of sequential things (lists, vectors, etc.) and returns their contents as a single, flat, lazy sequence. If the argument is non-sequential (numbers, maps, strings, nil, etc.), returns the original argument." {:static true} [x] (letfn [(flat [coll] (lazy-seq (when-let [c (seq coll)] (let [x (first c)] (if (sequential? x) (concat (flat x) (flat (rest c))) (cons x (flat (rest c))))))))] (if (sequential? x) (flat x) x)))Actually, flatten on a vector returns list, not a collection: