Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Realization timing of lazy sequence

(defn square [x]
  (do
    (println (str "Processing: " x))
    (* x x)))

(println (map square '(1 2 3 4 5)))

Why is the output

(Processing: 1 
Processing: 2 
1 Processing: 3 
4 Processing: 4 
9 Processing: 5 
16 25)

not

(Processing: 1
1 Processing: 2
4 Processing: 3 
9 Processing: 4 
16 Processing: 5 
25)

?

like image 782
alice Avatar asked Nov 19 '12 13:11

alice


2 Answers

Because map is lazy. It uses lazy-seq under the covers, which pre-caches the result of rest. So you see the two println statements appear when your code grabs the first value of the map sequence.

See also this blog post: Lazy Sequences

like image 67
noahlz Avatar answered Oct 06 '22 21:10

noahlz


println uses [[x & xs] xs] destructuring form in its implementation. This is equivelent to [x (first xs), xs (next xs)] and next is less lazy than rest, so it realizes the two items before printing the first.

For example,

=> (defn fn1 [[x & xs]] nil)
#'user/fn1
=> (fn1 (map square '(1 2 3 4 5)))
Processing: 1
Processing: 2
nil
like image 43
alice Avatar answered Oct 06 '22 22:10

alice