Incompatibility between generators and arrays in the Iterator protocol

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Incompatibility between generators and arrays in the Iterator protocol

Tim Jansen

Hi,

I am working on a collections library that supports the Iterable/Iterator protocol, but I ran into a stumbling block: the iterator protocol seems to work differently for arrays and generator functions. Array iterators set 'done' to true *after* the last element, but function generators set 'done' to true *on* the last element.

Is this incompatibility intentional, or or just an implementation issue in the browsers (tested on FF38 and Chrome 43)? I wasn't able to find any information on this. The ES6 draft from April '15 doesn't define when exactly 'done' is set.


Code example:

var a = ['a', 'b'];

var itA = a[Symbol.iterator];

itA.next();   // {value: 'a', done: false}

itA.next();   // {value: 'b', done: false} !!

itA.next();   // {value: undefined, done: true}


function* b() { 

  yield 'a'; 

  return 'b'; 

}

var itB = a[Symbol.iterator];

itB.next();   // {value: 'a', done: false}

itB.next();   // {value: 'b', done: true} !!!

itB.next();   // {value: undefined, done: true}

The difference is in the second invocation of next(), which returns true for generator functions. That protocol makes it impossible for me to support both generator functions and array iterators with the same implementation - at least if I want to support 'undefined' as a valid value in collections. I wouldn't be able to differentiate between an empty list ([]) and a list containing undefined ([undefined]).


Thanks,

Tim




_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Incompatibility between generators and arrays in the Iterator protocol

Kevin Smith

If you use yield instead of return in your generator function you'll get the desired results.  When using a generator function to implement iteration, you'll generally want to avoid returning a final value, since for-of ignores the return value.

The return value does have an important role to play in coroutine-style use cases.


On 2:20PM, Tue, Jun 30, 2015 Tim Jansen <[hidden email]> wrote:

Hi,

I am working on a collections library that supports the Iterable/Iterator protocol, but I ran into a stumbling block: the iterator protocol seems to work differently for arrays and generator functions. Array iterators set 'done' to true *after* the last element, but function generators set 'done' to true *on* the last element.

Is this incompatibility intentional, or or just an implementation issue in the browsers (tested on FF38 and Chrome 43)? I wasn't able to find any information on this. The ES6 draft from April '15 doesn't define when exactly 'done' is set.


Code example:

var a = ['a', 'b'];

var itA = a[Symbol.iterator];

itA.next();   // {value: 'a', done: false}

itA.next();   // {value: 'b', done: false} !!

itA.next();   // {value: undefined, done: true}


function* b() { 

  yield 'a'; 

  return 'b'; 

}

var itB = a[Symbol.iterator];

itB.next();   // {value: 'a', done: false}

itB.next();   // {value: 'b', done: true} !!!

itB.next();   // {value: undefined, done: true}

The difference is in the second invocation of next(), which returns true for generator functions. That protocol makes it impossible for me to support both generator functions and array iterators with the same implementation - at least if I want to support 'undefined' as a valid value in collections. I wouldn't be able to differentiate between an empty list ([]) and a list containing undefined ([undefined]).


Thanks,

Tim



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Incompatibility between generators and arrays in the Iterator protocol

Logan Smyth
In reply to this post by Tim Jansen
The value set when `done: true` is set is not considered part of the iterated list, which is why you are seeing what you are seeing. The expected behavior is defined as `done: false` for all yielded values, and `done: true` when iteration has completed. 

That same behavior also applies for `for...of` loops for instance. For example, see 13.7.5.13 #5c, as soon as 'done' becomes 'true' the loop exits, the returned value is ignored. Also the same can also be seen in Array.from in 22.1.2.1 #6.g.iv

On Tue, Jun 30, 2015 at 11:13 AM, Tim Jansen <[hidden email]> wrote:

Hi,

I am working on a collections library that supports the Iterable/Iterator protocol, but I ran into a stumbling block: the iterator protocol seems to work differently for arrays and generator functions. Array iterators set 'done' to true *after* the last element, but function generators set 'done' to true *on* the last element.

Is this incompatibility intentional, or or just an implementation issue in the browsers (tested on FF38 and Chrome 43)? I wasn't able to find any information on this. The ES6 draft from April '15 doesn't define when exactly 'done' is set.


Code example:

var a = ['a', 'b'];

var itA = a[Symbol.iterator];

itA.next();   // {value: 'a', done: false}

itA.next();   // {value: 'b', done: false} !!

itA.next();   // {value: undefined, done: true}


function* b() { 

  yield 'a'; 

  return 'b'; 

}

var itB = a[Symbol.iterator];

itB.next();   // {value: 'a', done: false}

itB.next();   // {value: 'b', done: true} !!!

itB.next();   // {value: undefined, done: true}

The difference is in the second invocation of next(), which returns true for generator functions. That protocol makes it impossible for me to support both generator functions and array iterators with the same implementation - at least if I want to support 'undefined' as a valid value in collections. I wouldn't be able to differentiate between an empty list ([]) and a list containing undefined ([undefined]).


Thanks,

Tim




_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Incompatibility between generators and arrays in the Iterator protocol

Ben Newman
In reply to this post by Kevin Smith
Kevin is right; I think the equivalence you're looking for is:

var arrayIter = [1, 2, ..., n][Symbol.iterator](); var genIter = (function*() { yield 1; yield 2; ... yield n; })();

On Tue, Jun 30, 2015 at 2:31 PM Kevin Smith <[hidden email]> wrote:

If you use yield instead of return in your generator function you'll get the desired results.  When using a generator function to implement iteration, you'll generally want to avoid returning a final value, since for-of ignores the return value.

The return value does have an important role to play in coroutine-style use cases.


On 2:20PM, Tue, Jun 30, 2015 Tim Jansen <[hidden email]> wrote:

Hi,

I am working on a collections library that supports the Iterable/Iterator protocol, but I ran into a stumbling block: the iterator protocol seems to work differently for arrays and generator functions. Array iterators set 'done' to true *after* the last element, but function generators set 'done' to true *on* the last element.

Is this incompatibility intentional, or or just an implementation issue in the browsers (tested on FF38 and Chrome 43)? I wasn't able to find any information on this. The ES6 draft from April '15 doesn't define when exactly 'done' is set.


Code example:

var a = ['a', 'b'];

var itA = a[Symbol.iterator];

itA.next();   // {value: 'a', done: false}

itA.next();   // {value: 'b', done: false} !!

itA.next();   // {value: undefined, done: true}


function* b() { 

  yield 'a'; 

  return 'b'; 

}

var itB = a[Symbol.iterator];

itB.next();   // {value: 'a', done: false}

itB.next();   // {value: 'b', done: true} !!!

itB.next();   // {value: undefined, done: true}

The difference is in the second invocation of next(), which returns true for generator functions. That protocol makes it impossible for me to support both generator functions and array iterators with the same implementation - at least if I want to support 'undefined' as a valid value in collections. I wouldn't be able to differentiate between an empty list ([]) and a list containing undefined ([undefined]).


Thanks,

Tim



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Incompatibility between generators and arrays in the Iterator protocol

Allen Wirfs-Brock
In reply to this post by Tim Jansen

On Jun 30, 2015, at 11:13 AM, Tim Jansen wrote:

Is this incompatibility intentional, or or just an implementation issue in the browsers (tested on FF38 and Chrome 43)? I wasn't able to find any information on this. The ES6 draft from April '15 doesn't define when exactly 'done' is set.


sure it does:

For example,





_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Incompatibility between generators and arrays in the Iterator protocol

Tim Jansen
In reply to this post by Kevin Smith
I see. I always considered the last value to be a part of the iteration, but if you don't (and for(of) treats it like that) it makes perfect sense.

Thanks!
Tim


On Tue, Jun 30, 2015 at 8:31 PM, Kevin Smith <[hidden email]> wrote:

If you use yield instead of return in your generator function you'll get the desired results.  When using a generator function to implement iteration, you'll generally want to avoid returning a final value, since for-of ignores the return value.

The return value does have an important role to play in coroutine-style use cases.


On 2:20PM, Tue, Jun 30, 2015 Tim Jansen <[hidden email]> wrote:

Hi,

I am working on a collections library that supports the Iterable/Iterator protocol, but I ran into a stumbling block: the iterator protocol seems to work differently for arrays and generator functions. Array iterators set 'done' to true *after* the last element, but function generators set 'done' to true *on* the last element.

Is this incompatibility intentional, or or just an implementation issue in the browsers (tested on FF38 and Chrome 43)? I wasn't able to find any information on this. The ES6 draft from April '15 doesn't define when exactly 'done' is set.


Code example:

var a = ['a', 'b'];

var itA = a[Symbol.iterator];

itA.next();   // {value: 'a', done: false}

itA.next();   // {value: 'b', done: false} !!

itA.next();   // {value: undefined, done: true}


function* b() { 

  yield 'a'; 

  return 'b'; 

}

var itB = a[Symbol.iterator];

itB.next();   // {value: 'a', done: false}

itB.next();   // {value: 'b', done: true} !!!

itB.next();   // {value: undefined, done: true}

The difference is in the second invocation of next(), which returns true for generator functions. That protocol makes it impossible for me to support both generator functions and array iterators with the same implementation - at least if I want to support 'undefined' as a valid value in collections. I wouldn't be able to differentiate between an empty list ([]) and a list containing undefined ([undefined]).


Thanks,

Tim



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Fly: A build system based in promises, generators and co-routines.

Bucaran
Hi folks

I have been fidingly with ES6 for over a year now, but for even longer I have been longing for a more expressive and honestly simpler build system / automation tool. I have dabbled with gulp, grunt and brunch and while they do get the job done and are great in their own way, I feel they are also very complex and carry a significant cognitive load. 

So, here is yet a new build system / task automator / promise-pipeline, based in generators and co-routines and written entirely in ES6 (transpiling with babel).

Similar to Gulp, _Fly_ favors code over configuration, but aims to provide a [definitive simpler way](https://github.com/flyjs/fly#flyfile) to describe and compose tasks.

Check it out and please let me know what you think. If you agree with my mission, please help me make this the build system the JS community really deserves.

Cheers
Jorge Bucaran

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss