Truthiness, nil, and Booleans
Prerequisites: Keywords and symbols
Clojure's rule is short: only false and nil are "falsy".
Everything else — including 0, "", and empty collections — counts as
true in a condition.
(doseq [v [true false nil 0 "" [] {} "text"]]
(println (pr-str v) "->" (if v "truthy" "falsy")))
true -> truthy
false -> falsy
nil -> falsy
0 -> truthy
"" -> truthy
[] -> truthy
{} -> truthy
"text" -> truthy
(doseq runs its body once per item — covered with the other loops
later. pr-str shows a value as data.)
Checking for empty or nil
(println (nil? nil) (nil? false))
(println (some? 0) (some? nil))
(println (empty? []) (empty? "") (empty? [1]))
(println (seq []) (seq [1 2]))
(println (true? 1) (boolean 1) (boolean nil))
true false
true false
true true false
nil (1 2)
false true false
nil?/some?check fornil.empty?checks for an empty collection or string.(seq coll)returnsnilfor an empty collection — the idiomatic "is there anything in here?" test:(when (seq items) ...).
and, or, not
(println (and true 1 "yes")) ; last truthy value
(println (and 1 nil 3)) ; first falsy value
(println (or nil false "default")) ; first truthy value
(println (not nil) (not 0))
(defn port [config] (or (:port config) 8080))
(println (port {:port 3000}) (port {}))
yes
nil
default
true false
3000 8080
and and or return values, not just true/false, and stop as
soon as the answer is known. (or x default) is the usual way to supply
a default.
nil punning
Most core functions treat nil as an empty collection, so it rarely
causes errors:
(println (count nil) (first nil) (conj nil 1) (get nil :a) (str nil))
0 nil (1) nil