How do you return from a function early in Clojure?

compman picture compman · Sep 20, 2011 · Viewed 19.9k times · Source

Common Lisp has return-from; is there any sort of return in Clojure for when you want to return early from a function?

Answer

Ben Kovitz picture Ben Kovitz · May 7, 2016

When you need to bail out of a computation early, you need a way to do that, not an argument from purists. Usually you need it when you're reducing a big collection and a certain value indicates that there's no point in further processing the collection. To that end, the ever-practical Clojure provides the reduced function.

A simple example to illustrate is that when multiplying a sequence of numbers, if you encounter a zero, you already know that the final result will be zero, so you don't need to look at the rest of the sequence. Here's how you code that with reduced:

(defn product [nums]
  (reduce #(if (zero? %2)
               (reduced 0.0)
               (* %1 %2))
          1.0
          nums))

reduced wraps the value you give it in a sentinel data structure so that reduce knows to stop reading from the collection and simply return the reduced value right now. Hey, it's pure-functional, even!

You can see what's going on if you wrap the above if in a do with a (println %1 %2):

user=> (product [21.0 22.0 0.0 23.0 24.0 25.0 26.0])
1.0 21.0
21.0 22.0
462.0 0.0
0.0

user=> (product [21.0 22.0 23.0 24.0 25.0 26.0])
1.0 21.0
21.0 22.0
462.0 23.0
10626.0 24.0
255024.0 25.0
6375600.0 26.0
1.657656E8