Axel Rauschmayer wrote:
Given that redundant calls to `return()` don’t make a difference (h/t Bergi)
I'm sorry, that was not 100% accurate. I only referred to `.return(x)`
returning {done:true, value:x} and `.throw(e)` being equivalent to
`throw e;` when the generator was never started or is already completed
(http://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresumeabrupt).
In fact, there are generators that behave differently when being
prematurely aborted and attempted to be closed multiple times.
A contrived example:
function* unstoppableCounter(n) {
try {
while (true)
yield n++;
} finally {
console.log("unclosable!");
yield* unstoppableCounter(n);
}
}
var counter = unstoppableCounter(0);
var i=5;
for (var x of counter) {
console.log(x);
if (!--i) break;
}
i=4;
for (var x of counter) {
console.log(x);
if (!--i) break;
}
Every call of `counter.return()` here would actually log "unclosable!",
increase the counter and yield {done:false, value:…} - in general, might
have side effects. So we shouldn't do it arbitrarily often.
> couldn’t the iteration protocol be simpler if iterators were always
closed. “Manually implemented” iterators could be written without the
check in line (A)
I don't think that's how an explicit iterator would be written.
Shouldn't it look more like
…
next() {
if (iterationIsDone()) {
cleanUp();
return {done: true};
} else {
return {value: nextValue(), done: false};
}
}
Of course that assumes that we don't have a return value, and `next()`
is no more called after it returned `done: true` once (otherwise we'd
clean up multiple times).
Maybe better:
…
next() {
if (iterationIsDone()) {
return {done: true};
} else {
let result = {value: nextValue(), done: iterationIsDone()};
if (result.done) cleanUp(); // (B)
return result;
}
}
Admittedly, that has the line you argued against again…
Bergi
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss