Skip to content

Instantly share code, notes, and snippets.

@gerritjvv
Created July 8, 2013 12:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gerritjvv/5948398 to your computer and use it in GitHub Desktop.
Save gerritjvv/5948398 to your computer and use it in GitHub Desktop.
Partitioning Lazy Sequences
Caution: Partitioning lazy sequence code freeze
(def l [1 2 3 4 5])
;create a simple lazy sequence function testing only
;(rdr l) returns a lazy sequence from l
(def rdr (fn reader[x] (cons (first x) (lazy-seq (reader (rest x))))))
;the line below will freeze
(doall (partition-all 2 (rdr l)) )
;add-in a take-while statement do exit the lazy sequence on nil
(doall (partition-all 2 (take-while (complement nil?) (rdr l))))
@czan
Copy link

czan commented Jul 11, 2013

Your issue here isn't that your sequence is lazy, it's that your sequence is infinite. Your rdr function returns an infinite list starting with the argument it's passed, then continuing with nils forever (try (take 100 (rdr l)) and you can see the nils; feel free to vary that 100 however you like).

If you redefined rdr like this then you wouldn't have any issues:

(def rdr (fn reader [x] (if (seq x) (cons (first x) (lazy-seq (reader (rest x)))))))

The thing you missed is that your rdr must return an empty sequence for the end of the lazy sequence. (cons nil x) is non-empty, no matter what x is (assuming that cons call makes sense), so your rdr always returns a non-empty sequence, and therefore never ends.

This isn't your whole problem, though. partition-all can handle infinite lists, too. (take 10 (partition-all 2 (rdr l))) will terminate as you'd expect, but your doall is trying to force an infinite collection. This can't possibly terminate, because you'll never reach the end of the sequence.

Your take-while solves the problem by truncating your sequence before the nils, but it won't work properly if your l is different. As an example, try using (def l [1 2 3 nil 4 5 6]). Now your final line doesn't give me back my whole l, like it should. Using the rdr function I provided above along with your line 9 solves this problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment