Why does this bit of Clojure code:
user=> (map (constantly (println "Loop it.")) (range 0 3))
Yield this output:
Loop it.
(nil nil nil)
I'd expect it to print "Loop it" three times as a side effect of evaluating the function three times.
constantly
doesn't evaluate its argument multiple times. It's a function, not a macro, so the argument is evaluated exactly once before constantly
runs. All constantly
does is it takes its (evaluated) argument and returns a function that returns the given value every time it's called (without re-evaluating anything since, as I said, the argument is evaluated already before constantly
even runs).
If all you want to do is to call (println "Loop it")
for every element in the range, you should pass that in as the function to map instead of constantly
. Note that you'll actually have to pass it in as a function, not an evaluated expression.
As sepp2k rightly points out constantly
is a function, so its argument will only be evaluated once.
The idiomatic way to achieve what you are doing here would be to use doseq
:
(doseq [i (range 0 3)]
(println "Loop it."))
Or alternatively dotimes
(which is a little more concise and efficient in this particular case as you aren't actually using the sequence produced by range
):
(dotimes [i 3]
(println "Loop it."))
Both of these solutions are non-lazy, which is probably what you want if you are just running some code for the side effects.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With