Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

laziness does not work as expected

(defn seq-trial
  []
  (map #(do (println "hello " %) (inc %)) (range 10)))

(take 3 (seq-trial))

The code snippt above when evaluated prints out the following -

(hello 0 hello 1 hello 2 hello 3 hello 4 hello 5 hello 6 hello 7 hello 8 hello 9 1 2 3)

Because map returns a lazy sequence I expected this to print only -

(hello 0 hello 1 hello 2 1 2 3)

Why is the entire list evaluated here?

like image 487
Pranav Avatar asked Mar 07 '13 09:03

Pranav


1 Answers

This is because of a performance optimization called chunking. Essentially the sequence is realised in groups of n items called chunks. This means you need to take care with any side effects in your mapping function. The end result is correct tho, you still get a sequence of the correct length returned

The default chunk size is 32, so if you increase your range to a value larger than that you will understand what's going on a bit better:

user> (defn seq-trial
  []
  (map #(do (println "hello " %) (inc %)) (range 100)))

user> (take 3 (seq-trial))
hello  0 ; 32 item 'chunk' realized...
hello  1

...

hello  30
hello  31
(1 2 3)  ; the expected returned value

If you need to avoid chunking there are options available

like image 107
sw1nn Avatar answered Sep 28 '22 02:09

sw1nn