Reputation: 7374
In the example code below I return a lazy list. What I would like to happen when someone calls count on the list is that some arbitrary function get executed instead and returns whatever I like.
(defn my-range [i limit]
(lazy-seq
(when (< i limit)
(cons i (my-range (inc i) limit)))))
(count (my-range 0 9)) returns whatever
I'm not sure if this should be possible: I have been looking at reify
but can't figure out if it can be used in this situation.
Upvotes: 4
Views: 203
Reputation: 91857
You can do this, but it's rather a lot of work: you have to implement all the sequence-related interfaces yourself, and delegate most of them to your lazy seq. Here's a sketch:
(defn my-range [i limit]
(let [ret (lazy-seq
(when (< i limit)
(cons i (my-range (inc i) limit))))]
(reify
clojure.lang.Counted
(count [this] 10)
clojure.lang.Sequential
clojure.lang.ISeq
(first [this] (.first ret))
(next [this] (.next ret))
(more [this] (.more ret))
(cons [this x] (.cons ret x))
(empty [this] (.empty ret))
(equiv [this x] (.equiv ret x))
(seq [this] (.seq ret)))))
And indeed (my-range 1 3)
returns a two-item sequence which claims to have a count of 10, which is what you wanted.
Upvotes: 4