Immediate closing of iterators

Chris Hansen renselp at gmail.com
Thu Dec 21 03:18:05 PST 2006


This means that you can't even delegate a call that returns a
generator without voiding this guarantee?

class CollectionWrapper {
  var collection = ...some collection...;
  function gen() {
    return this.collection.gen();
  }
}

var c = new CollectionWrapper();
for (i in c.gen())
  break;

If the guarantee is voided so easily, and by operations that users
will percieve as completely trivial, I think people should be very
reluctant to ever rely on it.  And then why even have it?


-- Chris

On 12/21/06, Brendan Eich <brendan at mozilla.org> wrote:
> On Dec 20, 2006, at 3:49 PM, Chris Hansen wrote:
>
> > In this case the generator shouldn't be closed.  If gen2 had been
> > defined as
> >
> > function gen2() {
> >  return gen1();
> > }
> >
> > I would expect that it should.
>
> This is, as you say, asking for a full reference graph analysis.  We
> don't propose that.
>
> Consider two cases:
>
> 1. The Mozilla bug Jeff Thompson mentioned, https://
> bugzilla.mozilla.org/show_bug.cgi?id=349326, wants only a generator-
> iterator created "under the hood" to be closed promptly:
>
>    for (i in o)
>      break;
>
> where o denotes some object that's not an iterator -- an object that
> does not have an iterator::get method at all, or whose iterator::get
> returns a different object (o is the iterable, the returned object is
> its iterator).
>
> In this case, the for-in loop can tell whether it is calling a well-
> known iterator::get native method, or the default used when there is
> no o.iterator::get, whose result is newborn and where the result
> can't escape.  The returned iterator could be a generator-iterator:
>
>    o.iterator::get = function () { yield 1; yield 2 }
>
> The internal Generator class's iterator::get method (called
> __iterator__ in JS1.7 in Firefox, for want of full namespace support)
> is immutable (in ECMA-262 terms a generator-iterator's iterator::get
> property has the ReadOnly and DontDelete attributes set).  This
> method returns its |this| parameter, since a generator is an iterator.
>
> The for-in loop can tell whether o's iterator::get (mutable, but it
> doesn't matter for this analysis) references a generator-function.
> It knows that the generator-function will return a new generator-
> iterator that can't escape, because the Generator class prototype's
> iterator::get method can't be replaced or shadowed, so its return
> value can't be spied on.  Therefore in this case, the implementation
> can guarantee prompt close without a full heap scan.
>
> 2. To handle the
>
>    for (i in gen())
>      break;
>
> case, the implementation would need to recognize gen, whether via
> static analysis in strict mode or in any sufficiently optimizing
> implementation, or dynamically in standard mode or in cases where
> static analysis can't decide, as a generator function.  At this point
> the analysis for case 1 applies.
>
> Anything else (function returning generator-iterator that might have
> escaped to a global, etc.) defeats the prompt close promise.
>
> Does this work for the cases users care about?  I believe it does,
> but welcome counterexamples.
>
> /be
>



More information about the Es4-discuss mailing list