Sometimes you need to perform a side effect for each element in a sequence. For the sake of argument, let's say we want to
prn each of the items in
[0 1 2 3 4].
The existing core function
doseq can be used to accomplish this:
(doseq [x [0 1 2 3 4]] (prn x))
doseq is modeled after
for, lots of sophisticated things can be done using its mini-language, with
But, for applying
prn to each of the elements, you may be tempted to reach for this simpler looking
(map prn [0 1 2 3 4])
While this has appeal, it is laced with subtle issues surrounding evaluation and lazy sequences.
When you have something like this, you don't need to resort to
dorun to force evaluation. Instead, simply replace
run!, directly indicating your intent:
(run! prn [0 1 2 3 4])
As its docstring indicates,
run! is based on
reduce, which is eager, thus side-stepping any issues with lazy sequences. Also with
run!, no temporary sequence is produced and discarded as would be with
(dorun (map ...)).
And, since it is based on
reduce, this gives you a way to terminate processing early—you can use
(run! (fn [n] (if (< n 3) (prn n) (reduced nil))) (range))
This will apply
prn to only the first 3 elements of the infinite sequence returned by
(range) and terminate:
0 1 2
Note that, while the intent of
run!is that it be used solely for side effects (and thus is without a meaningful return value), it can return non-
nilin its initially-released form in Clojure and ClojureScript.
run! function was introduced with the work done to add transducers to Clojure 1.7, also first appearing in ClojureScript 0.0-2301.