Final iterator spec
What you're probably seeing is that the wiki no longer has up to date information. As things have been fully fleshed out in the es6 draft spec, the wiki is no longer up to date.
To answer your question, the iterator protocol hasn't changed back to using StopIteration. It's still { value, done }.
Thanks. Btw, where is the final spec stored?
You can find it in the Drafts page: harmony:specification_drafts.
And there is an HTML version here: people.mozilla.org/~jorendorff/es6-draft.html
I have a concern with these, which isn't 100% related to this thread, but is on the topic of iterators.
So, in Dart, we have this nice option of basically saying if (OBJ is Iterable)
, and we'll be able to know easily if an object conforms to that
particular interface.
Admittedly, this construct makes a lot more sense in Dart than it does in
Javascript, but it would be nice to have some kind of helper which will
determine if an object adheres to the Iterable interface. For instance,
Object.isIterable() => true
if the interface is present in the object's prototype.
It would be nice to have a convenience function for this largely because it feels like the VM should have an easier time knowing if an object is iterable or not, and may be able to cache its knowledge of the Iterable status of an object, for performance reasons.
Maybe it would be good if a helper function like this would also determine
that the return value of @@iterator()
also conforms to the Iterator
interface, or maybe that's not super important. But in any case, I could
see utilities like this being very helpful.
Maybe that ship has sailed, but if something like that would hurt the harmony status of iterators, I would be interested in hearing the specific reasons against it.
You can just do if (Symbol.iterator in potentialIterable)
.
Does that work cross-frame?
Yes
On Sun 02 Mar 2014 04:18, Domenic Denicola <domenic at domenicdenicola.com> writes:
You can just do
if (Symbol.iterator in potentialIterable)
.
Of course, this can introduce time-of-check-to-time-of-use bugs. Actually calling @@iterator on the iterable is more reliable.
Le 03/03/2014 10:11, Andy Wingo a écrit :
Of course, this can introduce time-of-check-to-time-of-use bugs. Actually calling @@iterator on the iterable is more reliable.
This only shifts the problem one step without really solving it. Calling @@iterator may return a non-iterator or may return something that looks like a iterator ('next' method), but throws when calling 'next'. I wonder if time-of-check-to-time-of-use bugs can be fully avoided entirely in JS? It might be possible to guarantee some properties in TypeScript assuming all consummers of a piece of code are checked by the TypeScript compiler.
In practice, it looks like JS devs have lived well with solution like Domenic's one.
On Mon 03 Mar 2014 10:35, David Bruant <bruant.d at gmail.com> writes:
This only shifts the problem one step without really solving it.
An iterable is simply an object with a callable @@iterator property. Calling @@iterator on an object and getting back a result is the sum-total of the iterator structural type -- so yes, this problem is solved.
Calling @@iterator may return a non-iterator or may return something that looks like a iterator ('next' method), but throws when calling 'next'.
This is why the for-of and yield* desugarings eagerly get the "next" property on the iterator, and then use that property as a method all the way through. (And of course it can throw.)
I wonder if time-of-check-to-time-of-use bugs can be fully avoided entirely in JS?
To an extent, but it's hard; see Object.freeze et al. Anyway that's beside the point. The spec tries to eliminate all the bugs that it can, and the case of "get me an iterator from an iterable" or "prepare to call 'next' on this presumed iterable" are cases in which it can help.
Le 3 mars 2014 à 10:46, Andy Wingo <wingo at igalia.com> a écrit :
An iterable is simply an object with a callable @@iterator property. Calling @@iterator on an object and getting back a result is the sum-total of the iterator structural type -- so yes, this problem is solved.
What does exactly the spec think what an iterable is? As far as I can tell, only Array.from
and %TypedArray%.from
test for iterability, and until bug 2486 is resolved, it is hard for us to guess, because there are really more than one possible answer, e.g.: Symbol.iterator in obj
and typeof obj[Symbol.iterator] === "function"
.
Section The Iterable Interface define something more restrictive than typeof obj[Symbol.iterator] === "function"
and less testable, given the requirements of the returned value of obj[Symbol.iterator]()
.
On Mon 03 Mar 2014 12:49, Claude Pache <claude.pache at gmail.com> writes:
What does exactly the spec think what an iterable is?
For what purpose? You rightly link to the denotation of Iterable; in context, it is used like this:
people.mozilla.org/~jorendorff/es6-draft.html#sec-getiterator
Then there are is the "next" operation on iterators:
people.mozilla.org/~jorendorff/es6-draft.html#sec-iteratornext
...and reading that I see that my memory was off, that we don't fetch the "next" method eagerly, and instead look up the "next" property each time. Apologies for the misinformation. Thus you can:
function *g() {
Object.defineProperty(g.prototype, 'next', {value:42});
yield 4;
}
for (var x of new g()) print (x);
The iterator is indeed an iterator when it is returned by @@iterator, but not after the first iteration :)
Basically: you are looking for looking for certainty in structural typing of mutable values. You won't find it; or rather, if you do find it, it lasts only until the next piece of code that could mutate the world.
Le 3 mars 2014 à 13:56, Andy Wingo <wingo at igalia.com> a écrit :
For what purpose?
For the purpose of giving the most reasonable answer to the if (OBJ is Iterable)
test that Caitlin Potter was asking for earlier in this thread.
For me, the answer should be the same as what makes Array.from
choose between the branch "iterable" and the branch "array-like". Which, as I have said, I cannot guess until bug 2486 is resolved. Deeper philosophical thoughts over what an iterable really is don't matter.
7.4.2 IsIterable ( obj )
The abstract operation IsIterable with argument obj performs the following steps:
- If Type(obj) is not Object, then return undefined.
- Let iteratorGetter be Get(obj, @@Iterator).
- Return iteratorGetter.
the above is the test that Array.from uses
An Iterable is an object that has a Symbol.iterator keyed property whose value is not undefined.
A well-fromed Iterable is one whose @@iterator method is a function that returns an object that supports the Iterator interface. If an iterable is not well-formed then using it as such is likely to result in runtime exceptions or buggy behavior.
A while back, the wiki Harmony draft spec for iterators changed from a Pythonic StopIteration approach to one where iterator objects return a {value : iter-value, done : bool} object. It since seems to have changed back. Is that the case, or am I misreading the situation?
It seems that Tracuer has yet to switch back, and before I bug the developers on that project I wanted to make sure that StopIteration is, in fact, back.