The Clojure function
(reductions + 0 (cycle [1 1 -1]))
produces a sequence [0 1 2 1 2 3 2 3 4 3 4 5 ...]. Unfortunately, this sequence isn't lazy.
As cycle
and reductions
are both documented as returning lazy sequences, I expected this combination of those functions to return a lazy sequence as well. Why doesn't it and how can I fix it to return the sequence lazily?
A more complex example that shows the same problem:
(reductions (fn [x f] (f x)) 0 (cycle [inc inc dec]))
(I show this, because this is the kind of version I would like to have working in the end, in case that makes any difference)
Clojure is not a lazy language. However, Clojure supports lazily evaluated sequences. This means that sequence elements are not available ahead of time and produced as the result of a computation. The computation is performed as needed.
Lazy Sequences in Clojure Clojure reference explains laziness as: Most of the sequence library functions are lazy, i.e. functions that return seqs do so incrementally, as they are consumed, and thus consume any seq arguments incrementally as well.
Unfortunately, this sequence isn't lazy.
Oh, yes, it is. We can quickly check that it is lazy by taking its first 10 elements:
(take 10 (reductions + 0 (cycle [1 1 -1])))
This very quickly returns an answer, which proves the sequence is lazy. Were the function not lazy, it would try to realize all the elements in the infinite sequence, and would blow the memory, or hang in an infinite loop.
What happens is that you're typing this func in the REPL, which tries to realize the sequence before showing it to you.
Edit: Use this tip to stop infinite loops if you ever found that you've triggered one or accidentally tried to realize an infinite seq.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With