On Wed, Jan 7, 2009 at 2:41 AM, Christian Vest Hansen
<karmazi...@gmail.com> wrote:
>
> On Wed, Jan 7, 2009 at 5:26 AM, Chouser <chou...@gmail.com> wrote:
>> Since I couldn't find any other class that uses this kind of
>> recursion for count(), it may be impossible to build a seq that
>> would still cause Cons.count() to overflow the stack, but I'm not
>> completely certain.
>
> We're all allowed to implement our own IPersistentCollections, but if
> they break 'count, then that would be a different bug, no?

Good question.

If your new collection (FooColl) implements seq() by returning a new
kind of Seq (FooColl$Seq) which in turn implements FooColl$Seq.count()
recursively as Cons did, it will break for long chains of FooColl$Seq.
This already strikes me as very unlikely, because it would only be
tempting to do in collections that accept an unmodified ISeq as part
of their contents.  But regardless, this would be entirely your own
new code and there's nothing I can do about it.

However, if FooColl$Seq avoids that error by using code like in this
patch, then we would have a more subtle issue.  A FooColl$Seq that
includes a Cons which in turn was cons'ed onto a FooColl$Seq that
includes a Cons ... and continues alternating like that for sufficient
depth would defeat this patch's fix.  Cons.count() would see that it's
'rest' is not a Cons, and would delegate to RT.count().  FooColl$Seq,
doing the same, would create a mutual recursion situation that could
overflow the stack.

I think we're now firmly off in the weeds far enough to declare "we
can cross that bridge when we get to it," happy in the belief that we
never will.  But even so, FooColl$Seq could push things a little
further by checking for Cons *or* FooColl$Seq and avoid recursing into
either one.  This would then postpone the problem until someone makes
an alternating chain of FooColl$Seq and BarColl$Seq.

I suppose the right way to handle this would be a signal Interface (or
perhaps just a method?) declaring if a seq's count() is "fast" or not.
Then Cons.count() could check this: if 'rest' is fast, defer to
RT.count(), otherwise inc in it's own loop.  This sounds to me like a
lot of work and a big patch for a problem nobody's likely to have.

--Chouser

--~--~---------~--~----~------------~-------~--~----~
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