Skip to content
AgileLogics
4 min read

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 for nil.
  • empty? checks for an empty collection or string.
  • (seq coll) returns nil for 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