Search code examples
recursionclojurelazy-evaluation

In Clojure, how can I write my own recursive function to work with lazy lists?


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"?


Solution

  • (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))))