Clojure constantly and display function

Why is this bit of Clojure code:

user=> (map (constantly (println "Loop it.")) (range 0 3)) 

Assume this output:

 Loop it. (nil nil nil) 

I expect him to print β€œLoop it” three times three times as a side effect of evaluating the function three times.

+6
source share
3 answers

constantly does not evaluate its argument several times. This is a function, not a macro, so the argument is evaluated exactly once before running constantly . Everything constantly does this, it takes its (evaluated) argument and returns a function that returns the given value each time it is called (without reevaluating anything, because, as I said, the argument is evaluated already before it constantly even works )

If all you want to do is call (println "Loop it") for each element in the range, you must pass this as a function to match instead of constantly . Note that you really need to pass it as a function, not an evaluated expression.

+9
source

You can get behavior close to your intent with usig repeatedly and lambda expression.

For instance:

 (repeatedly 3 #(println "Loop it")) 

If you are not in the REPL, this should be surrounded by dorun or similar. repeatedly is lazy.

+3
source

As sepp2k rightly points out, constantly is a function, so its argument will be evaluated only once.

The idiomatic way to achieve what you are doing here is to use doseq :

 (doseq [i (range 0 3)] (println "Loop it.")) 

Or, alternatively, dotimes (this is a bit more concise and effective in this particular case, since you are not actually using the sequence generated by range ):

 (dotimes [i 3] (println "Loop it.")) 

Both of these solutions are not lazy, which is probably what you need if you are just running some kind of code for side effects.

+3
source

Source: https://habr.com/ru/post/921127/


All Articles