laziness does not work as expected
Asked Answered
L

1

6
(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?

Lordship answered 7/3, 2013 at 9:48 Comment(0)
S
8

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

Stylish answered 7/3, 2013 at 10:3 Comment(1)
Side effects and lazy evaluation don't mix.Lubricous

© 2022 - 2024 — McMap. All rights reserved.