Sorry to resurrect this, but I noticed that there isn't an issue to
track this - is this something unlikely to be fixed officially for
1.0 ? The workaround you posted certainly works for me, but I just
wanted to make sure the actual core.clj filter implementation receives
the fix eventually.

On Dec 8 2008, 6:51 pm, Rich Hickey <richhic...@gmail.com> wrote:
> On Dec 8, 2008, at 8:56 PM, Stephen C. Gilardi wrote:
>
>
>
> > I think I finally see the problem. The "rest expression" infilter's 
> > call to lazy-cons has a reference to "coll" in it. That's all it  
> > takes for coll to be retained during the entire calculation of the  
> > rest.
>
> > (defnfilter
> >  "Returns a lazy seq of the items in coll for which
> >  (pred item) returns true. pred must be free of side-effects."
> >  [pred coll]
> >    (when (seq coll)
> >      (if (pred (first coll))
> >        (lazy-cons (first coll) (filterpred (rest coll)))
> >        (recur pred (rest coll)))))
>
> > The stye of fix that occurs to me involves peeling off coll from  
> > (frest coll) and (rrest coll) before continuing the lazy evaluation.
>
> > Posting so someone else can beat me to the answer. :-)
>
> I'm sorry I haven't chimed in sooner. I fully understand this. Yes,  
> it's the closure over coll in the rest portion, which means that after  
> finding some match, a subsequent call to rest that needs to skip a lot  
> will create a window over the interval where the seq will be realized.
>
> Eagerly evaluating (rest coll) won't work - the result will still be  
> in the closure while the recursion occurs. The only solutions involve  
> mutation infilter. Here's one way:
>
> (defnfilter
>    [pred coll]
>      (let [sa (atom (seq coll))
>            step (fn step []
>                    (when-let [s @sa]
>                      (let [x (first s)]
>                        (if (pred x)
>                          (lazy-cons x (do (swap! sa rest) (step)))
>                          (do (swap! sa rest)
>                              (recur))))))]
>        (step)))
>
> But it's not pretty. Fortunately, this segues with work I have been  
> doing on I/O and generators/streams. This will let you write things  
> like:
>
> (defnfilter-stream
>    "Returns a stream of the items in strm for which
>    (pred item) returns true. pred must be free of side-effects."
>    [pred strm]
>    (stream
>     #(let [x (next! strm)]
>        (if (or (eos? x) (pred x)) x (recur)))))
>
> (defnfilter
>     "Returns a lazy seq of the items in coll for which
>    (pred item) returns true. pred must be free of side-effects."
>   [pred coll]
>    (stream-seq (filter-stream pred (stream coll))))
>
> I'm still not done with this yet, so anyone who is stuck can use the  
> former version.
>
> Rich
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to