Search code examples
clojure

Printing inside a for loop


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?


Solution

  • 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)