I was practicing one Clojure tutorial and had to ensure that a for loop was executed so I put a println
command there, but it did not display messages.
So now I have got the question...
This code prints Tom's name:
(ns tutorial.core)
(defn -main []
(println 'Jane)
(for [a ['Tom]]
(println a))
;; 'Kate
)
tutorial.core> (-main)
Jane
Tom
(nil)
tutorial.core>
but this not:
(ns tutorial.core)
(defn -main []
(println 'Jane)
(for [a ['Tom]]
(println a))
'Kate
)
tutorial.core> (-main)
Jane
Kate
tutorial.core>
Why? In which cases can we expect that println
will not print texts?
for
is not a loop, it is a sequence comprehension which returns a lazy sequence. Your for
expression will therefore only execute its side-effects (calls to println
) when the returned sequence is evaluated. The REPL evaluates the values returned from your calls to -main
so it can print them.
Your first example returns a lazy sequence which is evaluted by the REPL causing the (println 'Tom)
call to be evaluated. Since println
returns nil
, the resulting sequence contains a single nil
value - this is the (nil)
you see in the output.
Your second example creates the same sequence but does not evaluate it, instead 'Kate
is returned from the function and the REPL prints that.
If you want an imperative for loop you should use doseq
:
(defn -main []
(println 'Jane)
(doseq [a ['Tom]]
(println a))
'Kate)