Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure coalesce function

SQL offers a function called coalesce(a, b, c, ...) that returns null if all of its arguments are null, otherwise it returns the first non-null argument.

How would you go about writing something like this in Clojure?

It will be called like this: (coalesce f1 f2 f3 ...) where the fi are forms that should only be evaluated if required. If f1 is non-nil, then f2 should not be evaluated -- it may have side-effects.

Maybe Clojure already offers such a function (or macro).

EDIT: Here a solution that I came up with (modified from Stuart Halloway's Programming Clojure, (and ...) macro on page 206):

(defmacro coalesce
  ([] nil)
  ([x] x)
  ([x & rest] `(let [c# ~x] (if c# c# (coalesce ~@rest)))))

Seems to work.

(defmacro coalesce
  ([] nil)
  ([x] x)
  ([x & rest] `(let [c# ~x] (if (not (nil? c#)) c# (coalesce ~@rest)))))

Fixed.

like image 654
Ralph Avatar asked Nov 03 '10 12:11

Ralph


1 Answers

What you want is the "or" macro.

Evaluates exprs one at a time, from left to right. If a form returns a logical true value, or returns that value and doesn't evaluate any of the other expressions, otherwise it returns the value of the last expression. (or) returns nil.

http://clojuredocs.org/clojure_core/clojure.core/or

If you only want nil and not false do a rewrite of and and name it coalesce.

Edit:

This could not be done as a function because functions evaluate all their arguments first. This could be done in Haskell because functions are lazy (not 100% sure about the Haskell thing).

like image 162
nickik Avatar answered Sep 20 '22 18:09

nickik