31

In Clojure what is the idiomatic way to test for nil and if something is nil then to substitute a value?

For example I do this a lot:

 let [ val    (if input-argument input-argument "use default argument")]

: but I find it repetitive having to use "input-argument" twice.

Tiago Mussi
  • 801
  • 3
  • 13
  • 20
yazz.com
  • 57,320
  • 66
  • 234
  • 385
  • If you do this a lot, in particular with input arguments, then maybe you are unaware that you can define [multiple signatures](http://stackoverflow.com/questions/3208347/how-to-create-default-value-for-function-argument-in-clojure) for a function. – coredump Oct 26 '15 at 02:23

4 Answers4

104

just use or:

(or input-argument "default")
Alex Ott
  • 80,552
  • 8
  • 87
  • 132
23

Alex's suggestion of "or" is indeed the idiomatic way to rewrite your example code, but note that it will not only replace nil values, but also those which are false.

If you want to keep the value false but discard nil, you need:

(let [val (if (nil? input-argument) "use default argument" input-argument)]
   ...)
sanityinc
  • 15,002
  • 2
  • 49
  • 43
  • The idiomatic answer thus might be to test for false, rather than for nil. By the way, as most work tends to be done on collections, rather than checking a single value, the map version of the above answer is:(map #(if (nil? %) "this was nil" %) coll) – bOR_ Apr 18 '11 at 07:56
  • 4
    Perhaps, but the OP was asking for the idiomatic way to check for `nil`. I can't comment on how he should have structured the unshown code surrounding his example. :-) – sanityinc Apr 18 '11 at 08:07
8

If you only bind the variable to do get the right value and not to use it twice there is a other way you can do it. There is a function in core called fnil.

You call fnil with the function you want to call and the default argument. This will return a function that will replace nils with the default value you provided.

The you can do one of the things depending on what you want. Creat a local function.

(let [default-fn (fnil fn-you-want-to call "default-argument")]
(default-fn input-argument))

In somecases (where you always have the same default argument) you can move to logic to do this out of your code and put it where to original function was (or wrap the function in case it in a other library).

(defn fn-you-want-to-call [arg] ....)
(def fn-you-want-to-call-default (fnil fn-you-want-to-call "default-argument"))

Then in your code its reduced to just

(fn-you-want-to-call-default input-argument)

More you can find here: http://clojuredocs.org/clojure_core/clojure.core/fnil

leeor
  • 17,041
  • 6
  • 34
  • 60
nickik
  • 5,809
  • 2
  • 29
  • 35
1

When the expected value is a boolean I recommend using an util fn.

(defn- if-nil [default val]
  (if (nil? val)
    default
    val))
    
(if-nil true (possible-false input))

Jp_
  • 5,973
  • 4
  • 25
  • 36