3

I was just trying to demonstrate laziness to someone, and I wrote a simple recursive function to process a list.

I assumed that it would be fine on an infinite list. But suddenly I got a "too much recursion" internal error.

Huh? I always write code that does that kind of thing. What's the problem?

But of course, normally I use built-in functions like map as the basis of other list-processing functions. This time I was trying to write my own recursive traversal. And, of course, that can't possibly work.

Here's what I wrote.

(defn q [xs] 
  (if (empty? xs) () 
    (cons (* (first xs) (first xs)) (q (rest xs)) )))

(take 10 (q (cycle '(1 2 3 4))))

So, how, in fact DO I write my own traversal functions that can handle lazy data structures in Clojure? Is there some kind of equivalent of a "yield"?

1

1 Answer 1

6
(defn q [xs] 
  (if (empty? xs) () 
    (lazy-seq  ;; <- here's our magic!
       (cons (* (first xs) (first xs)) (q (rest xs)) ))))

(take 10 (q (cycle '(1 2 3 4))))
Sign up to request clarification or add additional context in comments.

1 Comment

Good, but should be (defn q [xs] (lazy-seq (if ...))), so that an item from the input sequence is only realized when an item from the output sequence is demanded. As written, you always consume one more item than needed from the input seq. As a rule of thumb, when you produce a lazy sequence you should make sure that lazy-seq is wrapped around anything that forces an element of the input (like seq, first, rest, or empty?).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.