(println (iterate inc 0)): why does it even start to print?

When I run (println (iterate inc 0)) in my replica, I will get something like this:

 user=> (println (iterate inc 0)) (0 1 2 3 4 5 6 7 8 9 10 11 12 13 .................... 

My expectation when I run the code is that repl shows nothing and just gets stuck because (iterate inc 0) never ends. But I see (0 1 2 3 ...

(iterate inc 0) generates an infinite sequence that never returns. If this never ends, then why does println start printing values?

In other words, why (println xx) gets evaluated, even if the input never ends, is it evaluated?

+5
source share
2 answers

You should read lazy seqs in Clojure. They can create values ​​that can be consumed gradually, before the entire sequence is realized (which in this case will never happen).

It can help to think of it as how to click and pull. Instead of iterating over the entire list of values ​​and then pushing them to the println function (which will never happen), just repeat your hands, this is a lazy sequence, and println pulls the values ​​as needed. This is why (take 5 (iterate inc 0)) works; take only attempts to output 5 values ​​before stopping.

+8
source

Clojure printing is smarter than System.out.println ; It can be customized for different types . In the case of sequences, it goes through element after element, each prints when it goes β€” we do not need to wait until the whole sequence is evaluated to start printing. A.

In contrast, System.out.println , which calls toString before printing, behaves as soon as possible. It hangs forever, and does not print anything, because toString must evaluate the entire sequence - or at least it will hang forever if it does not run out of memory trying to build a string.

However, the whole expression is really stuck - if you were waiting for it to stop printing, you will always wait:

 (do (println (iterate inc 0)) (println "Never reached!")) 
+2
source

All Articles