Why does Array.from accept non-iterable arraylikes?

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

Why does Array.from accept non-iterable arraylikes?

Jason Orendorff
According to [1], Array.from will first try treating the argument as
an iterable, then as an arraylike. This is much better than just
arraylike. The committee considered making it iterable only, but
decided against it. The rationale recorded in the notes is:

    RW: No.

Rick, can you expand on that a bit? :-)

I propose changing it to iterable only. All builtin arraylike objects
are iterable now, including arguments, per the same discussion.[1]
Certainly the idea is for all DOM arraylikes to be iterable. So what
is this for?

  [1]: https://github.com/rwldrn/tc39-notes/blob/master/es6/2012-11/nov-29.md#revisit-nov-27-resolution-on-iterables-in-spread

-j

P.S. Rick: Thanks again for taking notes at the meetings. They're
indispensible. I've cloned the repo; grepping the notes has been super
useful too.
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Why does Array.from accept non-iterable arraylikes?

Erik Arvidsson
I'm with Jason here.

The only argument I can vaguely remember is that people want to be
able to use these on old browsers without @@iterator? But I don't see
why a polyfill could not tag things with __iterator__ or something
else?

On Mon, Jun 24, 2013 at 11:54 AM, Jason Orendorff
<[hidden email]> wrote:

> According to [1], Array.from will first try treating the argument as
> an iterable, then as an arraylike. This is much better than just
> arraylike. The committee considered making it iterable only, but
> decided against it. The rationale recorded in the notes is:
>
>     RW: No.
>
> Rick, can you expand on that a bit? :-)
>
> I propose changing it to iterable only. All builtin arraylike objects
> are iterable now, including arguments, per the same discussion.[1]
> Certainly the idea is for all DOM arraylikes to be iterable. So what
> is this for?
>
>   [1]: https://github.com/rwldrn/tc39-notes/blob/master/es6/2012-11/nov-29.md#revisit-nov-27-resolution-on-iterables-in-spread
>
> -j
>
> P.S. Rick: Thanks again for taking notes at the meetings. They're
> indispensible. I've cloned the repo; grepping the notes has been super
> useful too.
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss



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

Re: Why does Array.from accept non-iterable arraylikes?

Allen Wirfs-Brock

On Jun 24, 2013, at 9:07 AM, Erik Arvidsson wrote:

> I'm with Jason here.
>
> The only argument I can vaguely remember is that people want to be
> able to use these on old browsers without @@iterator? But I don't see
> why a polyfill could not tag things with __iterator__ or something
> else?

I think the other argument is that the Array iteration methods historically accept anything that vaguely looks "array-like".

If you can say:

Array.prototype.forEach({0:1,1:1,2:2,length:3}, n=> console.log(n));

why can't you say:

Array.from( {0:1,1:1,2:2,length:3}).forEach(n=>console.log(n));

or:

for (let n of Array.from( {0:1,1:1,2:2,length:3}))  console.log(n);

Allen





>
> On Mon, Jun 24, 2013 at 11:54 AM, Jason Orendorff
> <[hidden email]> wrote:
>> According to [1], Array.from will first try treating the argument as
>> an iterable, then as an arraylike. This is much better than just
>> arraylike. The committee considered making it iterable only, but
>> decided against it. The rationale recorded in the notes is:
>>
>>    RW: No.
>>
>> Rick, can you expand on that a bit? :-)
>>
>> I propose changing it to iterable only. All builtin arraylike objects
>> are iterable now, including arguments, per the same discussion.[1]
>> Certainly the idea is for all DOM arraylikes to be iterable. So what
>> is this for?
>>
>>  [1]: https://github.com/rwldrn/tc39-notes/blob/master/es6/2012-11/nov-29.md#revisit-nov-27-resolution-on-iterables-in-spread
>>
>> -j
>>
>> P.S. Rick: Thanks again for taking notes at the meetings. They're
>> indispensible. I've cloned the repo; grepping the notes has been super
>> useful too.
>> _______________________________________________
>> es-discuss mailing list
>> [hidden email]
>> https://mail.mozilla.org/listinfo/es-discuss
>
>
>
> --
> erik
> _______________________________________________
> 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: Why does Array.from accept non-iterable arraylikes?

Rick Waldron
In reply to this post by Jason Orendorff
On Mon, Jun 24, 2013 at 11:54 AM, Jason Orendorff <[hidden email]> wrote:
According to [1], Array.from will first try treating the argument as
an iterable, then as an arraylike. This is much better than just
arraylike. The committee considered making it iterable only, but
decided against it. The rationale recorded in the notes is:

    RW: No.

Rick, can you expand on that a bit? :-)

I propose changing it to iterable only. All builtin arraylike objects
are iterable now, including arguments, per the same discussion.[1]
Certainly the idea is for all DOM arraylikes to be iterable. So what
is this for?

  [1]: https://github.com/rwldrn/tc39-notes/blob/master/es6/2012-11/nov-29.md#revisit-nov-27-resolution-on-iterables-in-spread

-j

P.S. Rick: Thanks again for taking notes at the meetings. They're
indispensible. I've cloned the repo; grepping the notes has been super
useful too.

It's my pleasure and I'm glad you're finding them useful as a resource during implementation :)
 

The problem is that I can't really record my own input... while I'm talking, no one is taking notes. When I'm done talking, I'm taking notes. The example Brendan wrote on the board was to illustrate that a "helper" function could be used to turn arraylikes into iterables before being passed to Array.from. I said "no" because it contradicts the agreement made a few lines prior. 

While all builtin arraylikes are also iterable now, arraylikes created by non-built-in (assuming we both use "built-in" to refer to objects defined by ES) may not implement iterator protocol. Array.from, like Function.prototype.apply, will allow those objects to be turned into an array, eg. NodeList, DOMTokenList or jQuery objects. A cowpath that Array.from was intended to clear and pave was [].slice.call(arrayLike)/Array.prototype.slice.call(arrayLike). Also, web devs will be able to use a polyfilled Array.from in code that must run in browsers that don't/won't support spread (ie. older non-updating browsers). Hopefully this helps to clarify


Rick



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

Re: Why does Array.from accept non-iterable arraylikes?

Jason Orendorff
On Mon, Jun 24, 2013 at 11:43 AM, Rick Waldron <[hidden email]> wrote:
> While all builtin arraylikes are also iterable now, arraylikes created by
> non-built-in (assuming we both use "built-in" to refer to objects defined by
> ES) may not implement iterator protocol. Array.from, like
> Function.prototype.apply, will allow those objects to be turned into an
> array, eg. NodeList, DOMTokenList or jQuery objects.

NodeList and DOMTokenList are iterable in Firefox. NodeList is even
provisionally iterable per spec at the moment. It's marked as
`[ArrayClass]`:

  http://dom.spec.whatwg.org/#interface-nodelist

which means instances inherit from Array.prototype, including its
@@iterator method.

The infrastructure to make interfaces iterable, even without
[ArrayClass], also already exists in WebIDL:

  http://dev.w3.org/2006/webapi/WebIDL/#idl-iterators

In short, I wouldn't worry about other specs or software failing to
adopt iterability. The awful truth is, every other party to the
problem moves many times faster than new JS features propagate to the
last 10% of Web users. I'd be astonished if jQuery objects weren't
iterable long before ES6 features are considered generally available.
Iterability support is just a few lines of code, and jQuery users will
want to use Array.from!

> A cowpath that
> Array.from was intended to clear and pave was
> [].slice.call(arrayLike)/Array.prototype.slice.call(arrayLike).

Array.from should still satisfy that use case. Note that as proposed
currently, Array.from already isn't totally polyfillable; it is only
approxi-fill-able; dropping support for arraylikes will not change
that.

> Also, web
> devs will be able to use a polyfilled Array.from in code that must run in
> browsers that don't/won't support spread (ie. older non-updating browsers).

Ooh, interesting. Let's think this through.

In browsers that have neither iteratorSymbol nor array-spread syntax,
polyfills won't have access to either side of the iteration protocol.
They can't provide or consume iterables. So they'll have to either
"approxifill" Array.from or not try. I think they will not try.

I can imagine them using the arraylike protocol, with some extra cruft
behind the scenes to pick up particular non-arraylike iterables, such
as instances of their own Map and Set polyfills. That is, polyfills
*might* try to approx-i-fill Array.from using various workarounds; but
I'm not convinced we should carry those workarounds forward into ES6.

However I think the right answer is to make Array.from polyfillable.

If we change the name of the method from a symbol to plain
.iterator(), the iteration protocol will be fully accessible in pure
ES1-5 code. Functions that produce or consume iterables would become
accurately polyfillable. Array.from() would be polyfillable. The Map
and Set constructors. Polyfills would also be able to monkeypatch DOM
classes to make them iterable in old browsers.

There's a benefit for pure ES6 code too; it would be easier to make a
class iterable:

    class Table {
        *iterator() {
            ...
        }
    }

(Currently an extra scrap of code outside the class is needed, since
we don't have syntactic sugar for symbol-named methods.)

And jQuery could just add `iterator: [].iterator,` to an object
literal somewhere. Literally one line of code to make jQuery objects
iterable in browsers that have iteration support. No try-catch, eval,
or import needed.

I think TC39 made @@iterator a symbol on the theory that users would
want to build iterable Proxy-based string-key maps that would support
property-access syntax. I wonder if that rationale holds anymore, now
that there's the invoke trap.

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

Re: Why does Array.from accept non-iterable arraylikes?

Sam Tobin-Hochstadt
On Tue, Jun 25, 2013 at 11:30 AM, Jason Orendorff
<[hidden email]> wrote:
>
> I think TC39 made @@iterator a symbol on the theory that users would
> want to build iterable Proxy-based string-key maps that would support
> property-access syntax.

My recollection is that we chose to make `iterator` a symbol because
we worried about taking the name "iterator" on lots of existing
objects.

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

Re: Why does Array.from accept non-iterable arraylikes?

Jason Orendorff
On Tue, Jun 25, 2013 at 10:42 AM, Sam Tobin-Hochstadt <[hidden email]> wrote:
>> I think TC39 made @@iterator a symbol on the theory that users would
>> want to build iterable Proxy-based string-key maps that would support
>> property-access syntax.
>
> My recollection is that we chose to make `iterator` a symbol because
> we worried about taking the name "iterator" on lots of existing
> objects.

What kind of existing code would be a problem?

Firefox added Array.prototype.iterator a year ago. It has shipped in
the release browser, and it's been fine.

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

Re: Why does Array.from accept non-iterable arraylikes?

Sam Tobin-Hochstadt
On Tue, Jun 25, 2013 at 11:58 AM, Jason Orendorff
<[hidden email]> wrote:

> On Tue, Jun 25, 2013 at 10:42 AM, Sam Tobin-Hochstadt <[hidden email]> wrote:
>>> I think TC39 made @@iterator a symbol on the theory that users would
>>> want to build iterable Proxy-based string-key maps that would support
>>> property-access syntax.
>>
>> My recollection is that we chose to make `iterator` a symbol because
>> we worried about taking the name "iterator" on lots of existing
>> objects.
>
> What kind of existing code would be a problem?
>
> Firefox added Array.prototype.iterator a year ago. It has shipped in
> the release browser, and it's been fine.

I think that's strong evidence against the worry, but I believe the
worry was something like what we've seen with `values` recently.

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

Re: Why does Array.from accept non-iterable arraylikes?

Anne van Kesteren
In reply to this post by Jason Orendorff
On Tue, Jun 25, 2013 at 4:58 PM, Jason Orendorff
<[hidden email]> wrote:
> On Tue, Jun 25, 2013 at 10:42 AM, Sam Tobin-Hochstadt <[hidden email]> wrote:
>> My recollection is that we chose to make `iterator` a symbol because
>> we worried about taking the name "iterator" on lots of existing
>> objects.
>
> What kind of existing code would be a problem?
>
> Firefox added Array.prototype.iterator a year ago. It has shipped in
> the release browser, and it's been fine.

E.g. HTMLCollection has named getters. Making it iterable without
breaking compatibility would be great.


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

Re: Why does Array.from accept non-iterable arraylikes?

Allen Wirfs-Brock

On Jun 25, 2013, at 10:19 AM, Anne van Kesteren wrote:

> On Tue, Jun 25, 2013 at 4:58 PM, Jason Orendorff
> <[hidden email]> wrote:
>> On Tue, Jun 25, 2013 at 10:42 AM, Sam Tobin-Hochstadt <[hidden email]> wrote:
>>> My recollection is that we chose to make `iterator` a symbol because
>>> we worried about taking the name "iterator" on lots of existing
>>> objects.
>>
>> What kind of existing code would be a problem?
>>
>> Firefox added Array.prototype.iterator a year ago. It has shipped in
>> the release browser, and it's been fine.
>
> E.g. HTMLCollection has named getters. Making it iterable without
> breaking compatibility would be great.
>

This design discussion really wasn't just about iterator.   In ES6 we have various property keys that are hooks deeply into either the semantics of core language features:  @@create, @@hasInstance, @@ToPrimitive, @@iterator, @@toStringTag, @@isRegExp.  

Anyone plugging into these hooks really should be intentional about what they are doing.  Accidentally  doing so my poor name choice may mot be disastrous but it is likely to be dificult to debug.   Using a symbol for these properties greatly reduces the likelihood of such an accident.

We could make an exception for iterator, but why?  That just introduces an inconsistency in the design.

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

Re: Why does Array.from accept non-iterable arraylikes?

Dean Landolt



On Tue, Jun 25, 2013 at 1:33 PM, Allen Wirfs-Brock <[hidden email]> wrote:

On Jun 25, 2013, at 10:19 AM, Anne van Kesteren wrote:

> On Tue, Jun 25, 2013 at 4:58 PM, Jason Orendorff
> <[hidden email]> wrote:
>> On Tue, Jun 25, 2013 at 10:42 AM, Sam Tobin-Hochstadt <[hidden email]> wrote:
>>> My recollection is that we chose to make `iterator` a symbol because
>>> we worried about taking the name "iterator" on lots of existing
>>> objects.
>>
>> What kind of existing code would be a problem?
>>
>> Firefox added Array.prototype.iterator a year ago. It has shipped in
>> the release browser, and it's been fine.
>
> E.g. HTMLCollection has named getters. Making it iterable without
> breaking compatibility would be great.
>

This design discussion really wasn't just about iterator.   In ES6 we have various property keys that are hooks deeply into either the semantics of core language features:  @@create, @@hasInstance, @@ToPrimitive, @@iterator, @@toStringTag, @@isRegExp.

Anyone plugging into these hooks really should be intentional about what they are doing.  Accidentally  doing so my poor name choice may mot be disastrous but it is likely to be dificult to debug.   Using a symbol for these properties greatly reduces the likelihood of such an accident.

We could make an exception for iterator, but why?  That just introduces an inconsistency in the design.


For properties that are expected to be looked up on object or its prototype unique symbols are the only way to go. Otherwise library code will end up littered with the `Class.prototype.method.call` pattern and we'll quickly lose the ability to coherently overload these methods anyway.

But there's still a huge win to be had in also defining hooks for this kind of functionality as static class methods on the built-ins, at least for the functionality that could otherwise be polyfilled correctly. Any functionality defined in this way will be instantly usable on the open web as soon as it gets the TC39 stamp of approval in Rick's meeting notes. That's a pretty big win for a very small amount of bloat.

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

Re: Why does Array.from accept non-iterable arraylikes?

Brandon Benvie-2
In reply to this post by Allen Wirfs-Brock
On 6/25/2013 10:33 AM, Allen Wirfs-Brock wrote:
> We could make an exception for iterator, but why? That just introduces
> an inconsistency in the design.

I think the motivation was to make it easier to polyfill, but I don't
think that argument holds for @@iterator. If you're attempting to
polyfill iteration, then you have to polyfill both ends of it; you have
to supply both the iterators as well as functions to consume those
iterators (since you can't polyfill for-of). That means you have control
over the protocol, and can opt to use something like "__iterator__".
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Why does Array.from accept non-iterable arraylikes?

Dean Landolt



On Tue, Jun 25, 2013 at 2:16 PM, Brandon Benvie <[hidden email]> wrote:
On 6/25/2013 10:33 AM, Allen Wirfs-Brock wrote:
We could make an exception for iterator, but why? That just introduces an inconsistency in the design.

I think the motivation was to make it easier to polyfill, but I don't think that argument holds for @@iterator. If you're attempting to polyfill iteration, then you have to polyfill both ends of it; you have to supply both the iterators as well as functions to consume those iterators (since you can't polyfill for-of). That means you have control over the protocol, and can opt to use something like "__iterator__".


You could, but your polyfills probably won't play well with other polyfills unless TC39 specifies a hook (normative or otherwise). Again, if the platform were to also define a secondary, static way to get and set an object's *iterator* a la Object.getPrototypeOf the interop problem is solved. It's hideous, sure, but it's really only necessary in library code.

It would be a shame of the lack of symbols is the only thing that kept pre-es6-supporting libraries from using iterators or other code that uses them.

 
_______________________________________________
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: Why does Array.from accept non-iterable arraylikes?

Jason Orendorff
In reply to this post by Brandon Benvie-2
On Tue, Jun 25, 2013 at 1:16 PM, Brandon Benvie <[hidden email]> wrote:
> On 6/25/2013 10:33 AM, Allen Wirfs-Brock wrote:
>>
>> We could make an exception for iterator, but why? That just introduces an
>> inconsistency in the design.
>
> I think the motivation was to make it easier to polyfill,

The motivation is to make it *possible* to polyfill correctly in
existing browsers. The protocol and related library features are
useful even without syntactic support.

> but I don't think
> that argument holds for @@iterator. If you're attempting to polyfill
> iteration, then you have to polyfill both ends of it; you have to supply
> both the iterators as well as functions to consume those iterators (since
> you can't polyfill for-of). That means you have control over the protocol,
> and can opt to use something like "__iterator__".

That kind of polyfill would not support other code that produces or
consumes the protocol.

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

Re: Why does Array.from accept non-iterable arraylikes?

Jason Orendorff
In reply to this post by Allen Wirfs-Brock
On Tue, Jun 25, 2013 at 12:33 PM, Allen Wirfs-Brock
<[hidden email]> wrote:
> This design discussion really wasn't just about iterator.   In ES6 we have various property keys that are hooks deeply into either the semantics of core language features:  @@create, @@hasInstance, @@ToPrimitive, @@iterator, @@toStringTag, @@isRegExp.
>
> Anyone plugging into these hooks really should be intentional about what they are doing.  Accidentally  doing so my poor name choice may mot be disastrous but it is likely to be dificult to debug.   Using a symbol for these properties greatly reduces the likelihood of such an accident.

This is indeed the counterargument. We should weigh this against the
benefits of iterators being polyfillable.

Let's take a concrete example. CKEditor 4 has a constructor named
CKEDITOR.dom.iterator:
  http://docs.ckeditor.com/#!/api/CKEDITOR.dom.iterator

The full extent of trouble we can expect from this naming conflict is
that if somone accidentally did

    arr = Array.from(CKEDITOR.dom);

the error message would say something like "iterator object has no
.next() method" rather than "Object not iterable". The mistake seems
unlikely in the first place, and the resulting error is actually no
harder to debug.

> We could make an exception for iterator, but why?  That just introduces an inconsistency in the design.

I think I mentioned several reasons. But mainly, iteration is worth
polyfilling, and making it polyfillable will put it in users' hands
literally years before symbols become universally available.

I don't think the inconsistency will even be all that unaesthetic. ES5
and previous have protocols too, using plain old string property
names: .length, .toString(), .valueOf(), and .prototype. One more is
not so bad, if it's something important.

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

Re: Why does Array.from accept non-iterable arraylikes?

Brandon Benvie-2
On 6/25/2013 1:09 PM, Jason Orendorff wrote:

> On Tue, Jun 25, 2013 at 12:33 PM, Allen Wirfs-Brock
> <[hidden email]> wrote:
>> This design discussion really wasn't just about iterator.   In ES6 we have various property keys that are hooks deeply into either the semantics of core language features:  @@create, @@hasInstance, @@ToPrimitive, @@iterator, @@toStringTag, @@isRegExp.
>>
>> Anyone plugging into these hooks really should be intentional about what they are doing.  Accidentally  doing so my poor name choice may mot be disastrous but it is likely to be dificult to debug.   Using a symbol for these properties greatly reduces the likelihood of such an accident.
> This is indeed the counterargument. We should weigh this against the
> benefits of iterators being polyfillable.
>
> Let's take a concrete example. CKEditor 4 has a constructor named
> CKEDITOR.dom.iterator:
>    http://docs.ckeditor.com/#!/api/CKEDITOR.dom.iterator
>
> The full extent of trouble we can expect from this naming conflict is
> that if somone accidentally did
>
>      arr = Array.from(CKEDITOR.dom);
>
> the error message would say something like "iterator object has no
> .next() method" rather than "Object not iterable". The mistake seems
> unlikely in the first place, and the resulting error is actually no
> harder to debug.
>
>> We could make an exception for iterator, but why?  That just introduces an inconsistency in the design.
> I think I mentioned several reasons. But mainly, iteration is worth
> polyfilling, and making it polyfillable will put it in users' hands
> literally years before symbols become universally available.
>
> I don't think the inconsistency will even be all that unaesthetic. ES5
> and previous have protocols too, using plain old string property
> names: .length, .toString(), .valueOf(), and .prototype. One more is
> not so bad, if it's something important.
>
> -j
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss

It's not just about backward compatibility, but also usability.
Mandating the addition of a non-symbol property in order to work with a
protocol (in this case the iterator protocol) is not good.

     var dict = Object.create(null);
     Object.defineProperty(dict, 'iterator', { value: function*(){
/*...*/ } })

It's `__proto__` all over again (looking at __proto__ as the "get/set
[[Prototype]] protocol"). Just say no.
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Why does Array.from accept non-iterable arraylikes?

Jason Orendorff
On Tue, Jun 25, 2013 at 3:19 PM, Brandon Benvie <[hidden email]> wrote:
> It's not just about backward compatibility, but also usability. Mandating
> the addition of a non-symbol property in order to work with a protocol (in
> this case the iterator protocol) is not good.

I don't buy this. Dynamic languages are full of protocols -- any time
a function calls a method on an argument, there's a protocol involved.
Duck typing.

Now that JS is getting symbols, things might change, but I expect
methods will still have plain old string names, just like always. The
class syntax was designed with this assumption.

>     var dict = Object.create(null);
>     Object.defineProperty(dict, 'iterator', { value: function*(){ /*...*/ }
> })

You can certainly still use an object as a worse-is-better dictionary;
you'd just leave the iterator code outside of the object:

    function* props(obj) {
        for (var k in obj)
            yield [k, obj[k]];
    }

    for (let [k, v] of props(dict))
        ...

This is probably what you'd want to do anyway. It's less code.

Since you want something iterable, it's also worth considering Map.
Iteration built in!

> It's `__proto__` all over again (looking at __proto__ as the "get/set [[Prototype]] protocol"). Just say no.

...Oh, that seems like a bit much. __proto__ was opt-out, for one
thing. Iterators are opt-in.

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

Re: Why does Array.from accept non-iterable arraylikes?

Brendan Eich-3
I think Jason wins. But the game is not over. Brandon?

/be

Jason Orendorff wrote:

> On Tue, Jun 25, 2013 at 3:19 PM, Brandon Benvie<[hidden email]>  wrote:
>
>> It's not just about backward compatibility, but also usability. Mandating
>>
>> the addition of a non-symbol property in order to work with a protocol (in
>>
>> this case the iterator protocol) is not good.
>
> I don't buy this. Dynamic languages are full of protocols -- any time
> a function calls a method on an argument, there's a protocol involved.
> Duck typing.
>
> Now that JS is getting symbols, things might change, but I expect
> methods will still have plain old string names, just like always. The
> class syntax was designed with this assumption.
>
>>      var dict = Object.create(null);
>>      Object.defineProperty(dict, 'iterator', { value: function*(){ /*...*/ }
>>
>> })
>
> You can certainly still use an object as a worse-is-better dictionary;
> you'd just leave the iterator code outside of the object:
>
>      function* props(obj) {
>          for (var k in obj)
>              yield [k, obj[k]];
>      }
>
>      for (let [k, v] of props(dict))
>          ...
>
> This is probably what you'd want to do anyway. It's less code.
>
> Since you want something iterable, it's also worth considering Map.
> Iteration built in!
>
>> It's `__proto__` all over again (looking at __proto__ as the "get/set [[Prototype]] protocol"). Just say no.
>>
>
> ...Oh, that seems like a bit much. __proto__ was opt-out, for one
> thing. Iterators are opt-in.
>
> -j
> _______________________________________________
> 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: Why does Array.from accept non-iterable arraylikes?

Brandon Benvie-2
In reply to this post by Jason Orendorff
On 6/25/2013 2:17 PM, Jason Orendorff wrote:

> On Tue, Jun 25, 2013 at 3:19 PM, Brandon Benvie <[hidden email]> wrote:
>> It's not just about backward compatibility, but also usability. Mandating
>> the addition of a non-symbol property in order to work with a protocol (in
>> this case the iterator protocol) is not good.
> I don't buy this. Dynamic languages are full of protocols -- any time
> a function calls a method on an argument, there's a protocol involved.
> Duck typing.
>
> Now that JS is getting symbols, things might change, but I expect
> methods will still have plain old string names, just like always. The
> class syntax was designed with this assumption.
>
>>      var dict = Object.create(null);
>>      Object.defineProperty(dict, 'iterator', { value: function*(){ /*...*/ }
>> })
> You can certainly still use an object as a worse-is-better dictionary;
> you'd just leave the iterator code outside of the object:
>
>      function* props(obj) {
>          for (var k in obj)
>              yield [k, obj[k]];
>      }
>
>      for (let [k, v] of props(dict))
>          ...
>
> This is probably what you'd want to do anyway. It's less code.
>
> Since you want something iterable, it's also worth considering Map.
> Iteration built in!
>
>> It's `__proto__` all over again (looking at __proto__ as the "get/set [[Prototype]] protocol"). Just say no.
> ...Oh, that seems like a bit much. __proto__ was opt-out, for one
> thing. Iterators are opt-in.
>
> -j

I agree that Map is better than dict, __proto__ is opt in, etc. Using
"iterator" smelled wrong to me and I hadn't fully thought through
exactly why. I should have made the point more directly.


Symbols provide a way of exposing meta-object protocol extension points
via the normal object protocol without requiring a cumbersome layer of
stratification, such as how Proxies separate the handler from the
exposed object (the proxy). Things that tie into syntax or spec
internals are prime targets for exposure through this way, such as
@@create and @@hasInstance (as well as proposed ideas such as @@call,
@@construct, @@geti, @@seti, etc.).

I think that the iteration protocol falls under the type of thing that
is better exposed through this layer of faux-stratification rather than
completely unstratified, due to its primary use in supporting syntax
(for-of). The reason there's any argument against it is because, unlike
most of the other extension points, there's some amount of "manually
cranking the wheel" that can be useful with the iteration protocol.

(I also don't think that polyfillability is a good argument here,
because as I said before, it's possible to create a polyfill that works
in ES3-ES6 that provides a compatibility layer over iteration.)
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Why does Array.from accept non-iterable arraylikes?

Allen Wirfs-Brock

On Jun 25, 2013, at 7:36 PM, Brandon Benvie wrote:

> On 6/25/2013 2:17 PM, Jason Orendorff wrote:
>> On Tue, Jun 25, 2013 at 3:19 PM, Brandon Benvie <[hidden email]> wrote:
>>> It's not just about backward compatibility, but also usability. Mandating
>>> the addition of a non-symbol property in order to work with a protocol (in
>>> this case the iterator protocol) is not good.
>> I don't buy this. Dynamic languages are full of protocols -- any time
>> a function calls a method on an argument, there's a protocol involved.
>> Duck typing.
>>
>> Now that JS is getting symbols, things might change, but I expect
>> methods will still have plain old string names, just like always. The
>> class syntax was designed with this assumption.
>>
>>>     var dict = Object.create(null);
>>>     Object.defineProperty(dict, 'iterator', { value: function*(){ /*...*/ }
>>> })
>> You can certainly still use an object as a worse-is-better dictionary;
>> you'd just leave the iterator code outside of the object:
>>
>>     function* props(obj) {
>>         for (var k in obj)
>>             yield [k, obj[k]];
>>     }
>>
>>     for (let [k, v] of props(dict))
>>         ...
>>
>> This is probably what you'd want to do anyway. It's less code.
>>
>> Since you want something iterable, it's also worth considering Map.
>> Iteration built in!
>>
>>> It's `__proto__` all over again (looking at __proto__ as the "get/set [[Prototype]] protocol"). Just say no.
>> ...Oh, that seems like a bit much. __proto__ was opt-out, for one
>> thing. Iterators are opt-in.
>>
>> -j
>
> I agree that Map is better than dict, __proto__ is opt in, etc. Using "iterator" smelled wrong to me and I hadn't fully thought through exactly why. I should have made the point more directly.
>
>
> Symbols provide a way of exposing meta-object protocol extension points via the normal object protocol without requiring a cumbersome layer of stratification, such as how Proxies separate the handler from the exposed object (the proxy). Things that tie into syntax or spec internals are prime targets for exposure through this way, such as @@create and @@hasInstance (as well as proposed ideas such as @@call, @@construct, @@geti, @@seti, etc.).
>
> I think that the iteration protocol falls under the type of thing that is better exposed through this layer of faux-stratification rather than completely unstratified, due to its primary use in supporting syntax (for-of). The reason there's any argument against it is because, unlike most of the other extension points, there's some amount of "manually cranking the wheel" that can be useful with the iteration protocol.

+1 and well said.
>
> (I also don't think that polyfillability is a good argument here, because as I said before, it's possible to create a polyfill that works in ES3-ES6 that provides a compatibility layer over iteration.)

I.m also dubious of the polyfill argument in this situation where the primary use case (for-of) isn't polyfillable.

We are already highly constrained by backwards compatibility requirements.  We shouldn't further constrain our options making requiring polyfillability.

The transition period is so much shorter then the future in front of us...  

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