18
votes

I want to supply a default value which can be overridden. I know I can use a ternary, like this:

(def foo (if (not (nil? bar)) bar baz))

But surely there is a more idiomatic way in Clojure to say "use bar, or baz if bar is nil.

Any suggestions?

3

3 Answers

28
votes

This will assign bar unless it is nil or false, and baz otherwise.

(def foo (or bar baz))

EDIT

If you wish to check for nil precisely, you can slightly optimize your original code, like this:

(def foo (if (nil? bar) baz bar))

I believe, this is the shortest possible way, though not idiomatic.

4
votes

Your question doesn't specifically ask about multiple vars, but if you did want this defaulting for more than one var the idiomatic way to do it is to use destructuring on map with :or defaults.

e.g. Take this function that takes a map argument m, the expected map has keys of :a, :b, & :c but if :b and/or :c are not supplied then the defaults are taken from the :or clause

(defn foo [m]
    (let [{:keys [a b c], :or {b 100 c 200}} m]
      (println "a:" a)
      (println "b:" b)
      (println "c:" c)))

user> (foo {:a 1 :b 2})
a: 1   ; no default, use supplied value
b: 2   ; value supplied, default ignored
c: 200 ; no value supplied, use default from :or
nil
2
votes

fnil is also an option:

user> (def default-to (partial fnil identity))
#'user/default-to

user> (let [bar :foo
            baz :default]
        ((default-to baz) bar))
:foo

user> (let [bar nil
            baz :default]
        ((default-to baz) bar))
:default