Re: Performance of iterator .next() as specified

2015-02-15 Thread Andrea Giammarchi
+1 and I've raised same concerns 2 years ago [1]

IIRC the outcome was that VM should be good enough to handle objects with
very short lifecycle, I'm still convinced (behind tests) that generators
are overkill for IoT devices (low clock and way lower RAM).

Having always same object per iteration makes sense to me at least until
it's done so that could be just a struct-like `{done: false, value: null}`
object and GC will be happier than ever.

Regards


[1]
http://webreflection.blogspot.co.uk/2013/06/on-harmony-javascript-generators.html

On Sun, Feb 15, 2015 at 10:06 AM, Katelyn Gadd k...@luminance.org wrote:

 As specified, iterator .next() seems to be required to return a new
 object instance for each iteration.

 In my testing (and in my theory, as an absolute) this is a real
 performance defect in the spec and it will make iterators inferior to
 all other forms of sequence iteration, to the extent that they may end
 up being used very rarely, and developers will be biased away from Map
 and Set as a result.

 The issue here is that the new object requirement means that every
 iteration produces GC pressure. I think that past APIs with this
 problem (for example TypedArray.set) have proven that 'a sufficiently
 smart VM can optimize this' is not representative of real VMs or real
 use cases.

 In the specific case of .next(), the method returning a new object on
 every iteration does not produce any actual improvement to usability:
 There is no realistic use case that requires saving multiple next()
 results from the same sequence, as the sequence itself represents (at
 least in most cases) a container or generated value sequence that is
 fully reproducible on demand.

 I think allowing (or requiring) implementations to return the same
 object instance from every .next() call, or perhaps as a usability
 compromise, reusing a pair of objects on a round-robin basis (so that
 you can keep around the current and prior result) would be a very good
 decision here.

 In my testing Map and Set are outperformed by a trivial Object or
 Array based data structure in every case, *despite the fact* that
 using an Object as a Map requires the use of Object.keys() to be able
 to sequentially iterate elements. The cost of iterator.next() in v8
 and spidermonkey is currently extremely profound and profiling shows
 all the time is being spent in object creation and GC. (To be fair,
 self-hosting of iterations might improve on this some.)

 Oddly enough, I consider the ES iterator spec to be a big improvement
 over C#'s IEnumerable, in terms of usability/API. But this is an area
 where it is intrinsically worse performance-wise than IEnumerable and
 that's unfortunate.

 -kg
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Performance of iterator .next() as specified

2015-02-15 Thread Katelyn Gadd
I'm certainly in favor of VMs improving to handle that, and adding
pressure for it is good. However, optimizing a TypedArray temporary
arg to .set() is a much simpler problem than doing the escape analysis
necessary to be certain a .next() result doesn't escape from a calling
scope and isn't used after a later next() call. Applying pressure will
be a good way to make sure VM authors do the work necessary for this
to happen, but if iterators are unacceptably slow in shipping
implementations for a year+ I think the odds are good that most
shipping software will avoid using them, at which point VM authors
will have no reason to optimize for primitives nobody uses. =[

The fixed layout of the iterator object would allow the GC to allocate
it cheaply and in the case of values (like ints) it wouldn't need to
trace it either - so that helps a lot. But I don't know how realistic
those optimizations are in practice.

On 15 February 2015 at 02:36, Andrea Giammarchi
andrea.giammar...@gmail.com wrote:
 +1 and I've raised same concerns 2 years ago [1]

 IIRC the outcome was that VM should be good enough to handle objects with
 very short lifecycle, I'm still convinced (behind tests) that generators are
 overkill for IoT devices (low clock and way lower RAM).

 Having always same object per iteration makes sense to me at least until
 it's done so that could be just a struct-like `{done: false, value: null}`
 object and GC will be happier than ever.

 Regards


 [1]
 http://webreflection.blogspot.co.uk/2013/06/on-harmony-javascript-generators.html

 On Sun, Feb 15, 2015 at 10:06 AM, Katelyn Gadd k...@luminance.org wrote:

 As specified, iterator .next() seems to be required to return a new
 object instance for each iteration.

 In my testing (and in my theory, as an absolute) this is a real
 performance defect in the spec and it will make iterators inferior to
 all other forms of sequence iteration, to the extent that they may end
 up being used very rarely, and developers will be biased away from Map
 and Set as a result.

 The issue here is that the new object requirement means that every
 iteration produces GC pressure. I think that past APIs with this
 problem (for example TypedArray.set) have proven that 'a sufficiently
 smart VM can optimize this' is not representative of real VMs or real
 use cases.

 In the specific case of .next(), the method returning a new object on
 every iteration does not produce any actual improvement to usability:
 There is no realistic use case that requires saving multiple next()
 results from the same sequence, as the sequence itself represents (at
 least in most cases) a container or generated value sequence that is
 fully reproducible on demand.

 I think allowing (or requiring) implementations to return the same
 object instance from every .next() call, or perhaps as a usability
 compromise, reusing a pair of objects on a round-robin basis (so that
 you can keep around the current and prior result) would be a very good
 decision here.

 In my testing Map and Set are outperformed by a trivial Object or
 Array based data structure in every case, *despite the fact* that
 using an Object as a Map requires the use of Object.keys() to be able
 to sequentially iterate elements. The cost of iterator.next() in v8
 and spidermonkey is currently extremely profound and profiling shows
 all the time is being spent in object creation and GC. (To be fair,
 self-hosting of iterations might improve on this some.)

 Oddly enough, I consider the ES iterator spec to be a big improvement
 over C#'s IEnumerable, in terms of usability/API. But this is an area
 where it is intrinsically worse performance-wise than IEnumerable and
 that's unfortunate.

 -kg
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Performance of iterator .next() as specified

2015-02-15 Thread Katelyn Gadd
As specified, iterator .next() seems to be required to return a new
object instance for each iteration.

In my testing (and in my theory, as an absolute) this is a real
performance defect in the spec and it will make iterators inferior to
all other forms of sequence iteration, to the extent that they may end
up being used very rarely, and developers will be biased away from Map
and Set as a result.

The issue here is that the new object requirement means that every
iteration produces GC pressure. I think that past APIs with this
problem (for example TypedArray.set) have proven that 'a sufficiently
smart VM can optimize this' is not representative of real VMs or real
use cases.

In the specific case of .next(), the method returning a new object on
every iteration does not produce any actual improvement to usability:
There is no realistic use case that requires saving multiple next()
results from the same sequence, as the sequence itself represents (at
least in most cases) a container or generated value sequence that is
fully reproducible on demand.

I think allowing (or requiring) implementations to return the same
object instance from every .next() call, or perhaps as a usability
compromise, reusing a pair of objects on a round-robin basis (so that
you can keep around the current and prior result) would be a very good
decision here.

In my testing Map and Set are outperformed by a trivial Object or
Array based data structure in every case, *despite the fact* that
using an Object as a Map requires the use of Object.keys() to be able
to sequentially iterate elements. The cost of iterator.next() in v8
and spidermonkey is currently extremely profound and profiling shows
all the time is being spent in object creation and GC. (To be fair,
self-hosting of iterations might improve on this some.)

Oddly enough, I consider the ES iterator spec to be a big improvement
over C#'s IEnumerable, in terms of usability/API. But this is an area
where it is intrinsically worse performance-wise than IEnumerable and
that's unfortunate.

-kg
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: TemplateLiteral tagged with super

2015-02-15 Thread Shinji Ikari
That case we can simply allow TemplateLiteral in Arguments. It will become
more consistent as well and causes less cognitive burden. We don't even
need to define MemberExpressionTemplateLiteral and CallExpression
TemplateLiteral any more. BTW, the only places where Arguments is referred
to are MemberExpression, CallExpression, and SuperCall.

Although it will be a rather breaking change because it will change the
precedence of expressions. For example, currently new a`x` is a
NewExpression. a`x` will be evaluated first. But with this change, it will
also be a simple MemberExpression. The a method will be [[Construct]] ed
with x as arg.

On Fri, Feb 13, 2015 at 8:01 PM, Gary Guo nbdd0...@hotmail.com wrote:

 If super TemplateLiteral is added, I will suggest we add new
 MemberExpression TemplateLiteral, which might be more useful in practice.

 --
 Date: Fri, 13 Feb 2015 20:55:49 -0500
 Subject: Re: TemplateLiteral tagged with super
 From: zenpars...@gmail.com
 To: al...@wirfs-brock.com
 CC: es-discuss@mozilla.org


  But what would it be good for.  Can anybody think of a practical use
 case for this?

 I can't.  And for what it's worth I didn't find *any* semantics obvious. I
 think in general it's best to limit the contexts in which super can occur,
 since it has different meanings depending on context.

 Seems like a defer thing to me.

 ___ es-discuss mailing list
 es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss

 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Subject: Performance of iterator .next() as specified

2015-02-15 Thread Benjamin (Inglor) Gruenbaum
 In my testing (and in my theory, as an absolute) this is a real
performance defect in the spec and it will make iterators inferior to
all other forms of sequence iteration, to the extent that they may end
up being used very rarely, and developers will be biased away from Map
and Set as a result.

Why?

Allocating a new object isn't really expensive, in cases it is and it
introduces GC pressure a clever engine can optimize it away by not really
allocating a new object where it is not required. Your suggestion can be
fully implemented by the engine already in the cases you speak of (where no
reference is kept) so there is no real speed benefit from it performance
wise. However in the case an iteration result is kept for later use this
can be destructive and create unpredictable results.

Also - of course for... of and iterating iterators right now is slower than
iterating in ways that have been there for years. Modern JS engines usually
add support for features and only then optimize them.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Subject: Performance of iterator .next() as specified

2015-02-15 Thread Katelyn Gadd
Replies inline

On 15 February 2015 at 06:16, Benjamin (Inglor) Gruenbaum
ing...@gmail.com wrote:
 In my testing (and in my theory, as an absolute) this is a real
 performance defect in the spec and it will make iterators inferior to
 all other forms of sequence iteration, to the extent that they may end
 up being used very rarely, and developers will be biased away from Map
 and Set as a result.

 Why?

To quote my original message:

In my testing Map and Set are outperformed by a trivial Object or
Array based data structure in every case, *despite the fact* that
using an Object as a Map requires the use of Object.keys() to be able
to sequentially iterate elements. The cost of iterator.next() in v8
and spidermonkey is currently extremely profound and profiling shows
all the time is being spent in object creation and GC. (To be fair,
self-hosting of iterations might improve on this some.)


To make this clearer: I have an existing dictionary container based on
Object and Object.keys. Replacing this with Map and Map iterator
produced a slowdown, and profiles showed almost all the time was being
spent in result object creation and GC.


 Allocating a new object isn't really expensive, in cases it is and it
 introduces GC pressure a clever engine can optimize it away by not really
 allocating a new object where it is not required. Your suggestion can be
 fully implemented by the engine already in the cases you speak of (where no
 reference is kept) so there is no real speed benefit from it performance
 wise. However in the case an iteration result is kept for later use this can
 be destructive and create unpredictable results.

It's expensive. In general object allocation  GCs show up in profiles
for almost every performance-sensitive application I work on. I'm sure
there are applications where this is not the case, though.
Also, to quote my original message:

I think that past APIs with this problem (for example TypedArray.set)
have proven that 'a sufficiently smart VM can optimize this' is not
representative of real VMs or real use cases.


I am sure that given some sufficient amount of compiler engineering,
the allocations could be entirely optimized out, but this is far from
a trivial case so odds are it will not happen soon.


 Also - of course for... of and iterating iterators right now is slower than
 iterating in ways that have been there for years. Modern JS engines usually
 add support for features and only then optimize them.

My point is that for my current test cases, were the .next()
allocation optimized out via a spec revision and *very trivial* change
to current implementations, the performance would be great. The
bottleneck would go away. This is much, much easier than having to
introduce sophisticated escape analysis  allocation removal into JS
VMs.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Subject: Performance of iterator .next() as specified

2015-02-15 Thread Katelyn Gadd
So there's no point in going in circles here, I just want to address
the statement:
Even if we allow this 'optimization' it will take the engines as much
time to implement it so there is no gain from this anyway.

My premise is that this is a rather obvious bottleneck and it applies
to new APIs with no for-loop equivalent. As far as I know, I cannot
use a for-loop to iterate over a Map or Set. So if I want to iterate
over Map or Set, I'm eating the cost of the current iterator API as
specified. The alternative is to use a custom implementation of those
containers (that is what I do right now, and will continue to do.)

Given the constraint that the .next() method is self-hosted in JS, my
proposal is trivial to implement. I think this is a reasonable
constraint, even though at present the API does not appear to be
self-hosted in SpiderMonkey. Many builtins are self-hosted in both
runtimes at present and more become self-hosted on a regular basis.
The current self-hosted JS would look like this:

function Iterator () {
  // ...
}

function next () {
  // ...
  return {
done: isDone,
value: value
  };
}

The proposal would change the self-hosted JS to:

function Iterator () {
  // ...
  this.$cachedResultObject = { done: false, value: null };
}

function next () {
  // ...
  this.$cachedResultObject.done = isDone;
  this.$cachedResultObject.value = value;
  return this.$cachedResultObject;
}

As long as the spec allows this behavior change (it's certainly
observable), that's all you really have to do at a basic level to make
this work. I hope it is obvious that a C++ engine-level implementation
of this optimization is not *significantly* more complex, though I
will not say it is 'easy'.

It is certainly, absolutely, I-will-bet-you-real-money simpler to do
this than to implement sufficiently smart escape analysis to be able
to optimize out the new object. I think if the next() method were
self-hosted and fully inlined into the caller, at that point it would
be possible for the .done and .value sets to be store-to-load
forwarded and the new object optimized out. That's the most realistic
case I can think of; I have yet to see a VM do that but I can imagine
it happening sometime soon, given that LuaJIT does it.

-kg

On 15 February 2015 at 07:16, Benjamin (Inglor) Gruenbaum
ing...@gmail.com wrote:
 On Sun, Feb 15, 2015 at 3:06 PM, Katelyn Gadd k...@luminance.org wrote:

 In my testing Map and Set are outperformed by a trivial Object or
 Array based data structure in every case, *despite the fact* that
 using an Object as a Map requires the use of Object.keys() to be able
 to sequentially iterate elements. The cost of iterator.next() in v8
 and spidermonkey is currently extremely profound and profiling shows
 all the time is being spent in object creation and GC. (To be fair,
 self-hosting of iterations might improve on this some.)


 Yes, this is of course true simply because iterating Set/Map was not
 optimized yet in V8/SpiderMoney since usually features are first implemented
 and then optimized. Benchmarking current naive engine implementations to
 make conclusions about the spec is a very risky thing to do. It's entirely
 possible for engines to optimize this. By the same logic I could say that
 `const` has bad performance because how it is currently implemented as much
 much slower than `var` in V8.

 I am sure that given some sufficient amount of compiler engineering,
 the allocations could be entirely optimized out, but this is far from
 a trivial case so odds are it will not happen soon.

 Right, I agree with you there it probably won't happen soon. Changing the
 spec won't change that fact. Remember that the engine doesn't actually need
 to allocate a new object in cases where it can reuse the old one safely
 since it's not used anymore - again, this can be solved at the engine level.

 My point is that for my current test cases, were the .next()
 allocation optimized out via a spec revision and *very trivial* change
 to current implementations, the performance would be great. The
 bottleneck would go away. This is much, much easier than having to
 introduce sophisticated escape analysis  allocation removal into JS
 VMs.

 This is something that can be solved at the VM level. VMs perform much much
 smarter optimizations than this already. There is no reason to sacrifice
 code correctness and the principle of least astonishment in order to get
 acceptable performance. Benchmarking against proof of concept
 implementations is counter-productive in my opinion. The engines are already
 'allowed' to use the same object when there is no observable difference.
 Even if we allow this 'optimization' it will take the engines as much time
 to implement it so there is no gain from this anyway.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Subject: Performance of iterator .next() as specified

2015-02-15 Thread Benjamin (Inglor) Gruenbaum
On Sun, Feb 15, 2015 at 3:06 PM, Katelyn Gadd k...@luminance.org wrote:

 In my testing Map and Set are outperformed by a trivial Object or
 Array based data structure in every case, *despite the fact* that
 using an Object as a Map requires the use of Object.keys() to be able
 to sequentially iterate elements. The cost of iterator.next() in v8
 and spidermonkey is currently extremely profound and profiling shows
 all the time is being spent in object creation and GC. (To be fair,
 self-hosting of iterations might improve on this some.)


Yes, this is of course true simply because iterating Set/Map was not
optimized yet in V8/SpiderMoney since usually features are first
implemented and then optimized. Benchmarking current naive engine
implementations to make conclusions about the spec is a very risky thing to
do. It's entirely possible for engines to optimize this. By the same logic
I could say that `const` has bad performance because how it is currently
implemented as much much slower than `var` in V8.

 I am sure that given some sufficient amount of compiler engineering,
the allocations could be entirely optimized out, but this is far from
a trivial case so odds are it will not happen soon.

Right, I agree with you there it probably won't happen soon. Changing the
spec won't change that fact. Remember that the engine doesn't actually need
to allocate a new object in cases where it can reuse the old one safely
since it's not used anymore - again, this can be solved at the engine level.

 My point is that for my current test cases, were the .next()
allocation optimized out via a spec revision and *very trivial* change
to current implementations, the performance would be great. The
bottleneck would go away. This is much, much easier than having to
introduce sophisticated escape analysis  allocation removal into JS
VMs.

This is something that can be solved at the VM level. VMs perform much much
smarter optimizations than this already. There is no reason to sacrifice
code correctness and the principle of least astonishment in order to get
acceptable performance. Benchmarking against proof of concept
implementations is counter-productive in my opinion. The engines are
already 'allowed' to use the same object when there is no observable
difference. Even if we allow this 'optimization' it will take the engines
as much time to implement it so there is no gain from this anyway.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Subject: Performance of iterator .next() as specified

2015-02-15 Thread joe
On Sun, Feb 15, 2015 at 7:16 AM, Benjamin (Inglor) Gruenbaum 
ing...@gmail.com wrote:


 This is something that can be solved at the VM level. VMs perform much
 much smarter optimizations than this already. There is no reason to
 sacrifice code correctness and the principle of least astonishment in order
 to get acceptable performance. Benchmarking against proof of concept
 implementations is counter-productive in my opinion. The engines are
 already 'allowed' to use the same object when there is no observable
 difference. Even if we allow this 'optimization' it will take the engines
 as much time to implement it so there is no gain from this anyway.

 __


Is 60,000 lines of source code a good enough proof of concept for you?

I don't see what the problem is.  My transpiler generators the following
ES5 code:

//for (var item in set)

var iter = obj.iterator();
while (1) {
   var ret = obj.next();

   if (ret.done) break;
   var item = ret.value;
   ...loop body
}

It works quite well.  You may be right about the VM vendors, however.  This
requirement basically makes JS useless for anything other than minor
scripting tasks.  The VM people may not have any choice but to optimize it.

Joe
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Subject: Performance of iterator .next() as specified

2015-02-15 Thread Benjamin (Inglor) Gruenbaum
This is actually exactly the kind of slow code Katelyn was talking about.
Also, you probably meant `set[Symbol.iterator]()` and `for... of`.

What Katelyn is talking about is optimizing .next in the example code to
not return a new object but to return the same one every time with
different values filled in. In order to optimize that with your transpiler
you'd need to implement your own `Set` and `Map` because like Katelyn
correctly noted `Set` and `Map` do not expose a fast way (in current
implementations) to iterate them at the moment - at least until engines
optimize them.

Katelyn is arguing it would be useful to allow the implementation to return
the same instance and I'm arguing the reason it's slow is because it's
benchmarked against a slow implementation that was not optimized yet but
can easily be - just like Katelyn noted as LuaJIT does.

When I can get more sound abstractions for no additional cost (eventually)
I'd rather not introduce implicit mutable state into the application.
Developers won't be aware of it being mutating and the whole notion of a
mutating-at-a-later-point return value is very error-prone in my opinion.

On Sun, Feb 15, 2015 at 3:35 PM, joe joe...@gmail.com wrote:



 On Sun, Feb 15, 2015 at 7:16 AM, Benjamin (Inglor) Gruenbaum 
 ing...@gmail.com wrote:


 This is something that can be solved at the VM level. VMs perform much
 much smarter optimizations than this already. There is no reason to
 sacrifice code correctness and the principle of least astonishment in order
 to get acceptable performance. Benchmarking against proof of concept
 implementations is counter-productive in my opinion. The engines are
 already 'allowed' to use the same object when there is no observable
 difference. Even if we allow this 'optimization' it will take the engines
 as much time to implement it so there is no gain from this anyway.

 __


 Is 60,000 lines of source code a good enough proof of concept for you?

 I don't see what the problem is.  My transpiler generators the following
 ES5 code:

 //for (var item in set)

 var iter = obj.iterator();
 while (1) {
var ret = obj.next();

if (ret.done) break;
var item = ret.value;
...loop body
 }

 It works quite well.  You may be right about the VM vendors, however.
 This requirement basically makes JS useless for anything other than minor
 scripting tasks.  The VM people may not have any choice but to optimize it.

 Joe


On Sun, Feb 15, 2015 at 3:35 PM, joe joe...@gmail.com wrote:



 On Sun, Feb 15, 2015 at 7:16 AM, Benjamin (Inglor) Gruenbaum 
 ing...@gmail.com wrote:


 This is something that can be solved at the VM level. VMs perform much
 much smarter optimizations than this already. There is no reason to
 sacrifice code correctness and the principle of least astonishment in order
 to get acceptable performance. Benchmarking against proof of concept
 implementations is counter-productive in my opinion. The engines are
 already 'allowed' to use the same object when there is no observable
 difference. Even if we allow this 'optimization' it will take the engines
 as much time to implement it so there is no gain from this anyway.

 __


 Is 60,000 lines of source code a good enough proof of concept for you?

 I don't see what the problem is.  My transpiler generators the following
 ES5 code:

 //for (var item in set)

 var iter = obj.iterator();
 while (1) {
var ret = obj.next();

if (ret.done) break;
var item = ret.value;
...loop body
 }

 It works quite well.  You may be right about the VM vendors, however.
 This requirement basically makes JS useless for anything other than minor
 scripting tasks.  The VM people may not have any choice but to optimize it.

 Joe

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Subject: Performance of iterator .next() as specified

2015-02-15 Thread Kevin Smith

 When I can get more sound abstractions for no additional cost (eventually)
 I'd rather not introduce implicit mutable state into the application.
 Developers won't be aware of it being mutating and the whole notion of a
 mutating-at-a-later-point return value is very error-prone in my opinion.


Right. Mutating the returned object isn't really tenable from a usability
point of view.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Subject: Performance of iterator .next() as specified

2015-02-15 Thread joe
Again, where does this mutation occur?  The spec shouldn't allow any such
thing to begin with; it should mandate exactly what my compiler does: as
soon as .next returns, copy .value into the loop variable.  The developer
shouldn't have any access to the return value from within the loop at all;
if he does, that should (ideally) be considered a violation of the standard.

On Sun, Feb 15, 2015 at 8:09 AM, Kevin Smith zenpars...@gmail.com wrote:

 When I can get more sound abstractions for no additional cost (eventually)
 I'd rather not introduce implicit mutable state into the application.
 Developers won't be aware of it being mutating and the whole notion of a
 mutating-at-a-later-point return value is very error-prone in my opinion.


 Right. Mutating the returned object isn't really tenable from a usability
 point of view.


 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Subject: Performance of iterator .next() as specified

2015-02-15 Thread Benjamin (Inglor) Gruenbaum
Joe, I don't think we're having the same discussion.

Again, this is about the issue Katelyn raised about the return value of
`.next`.

Katelyn suggested that the return value of a `.next` call in the iteration
protocol - an object of the form `{value: value, done: boolean}` should be
allowed to be reused between calls - so an iterator can return _the same_
object without allocating a new one.

I argue (and from what I understand Kevin agrees with me) that allowing
this is error prone and might cause surprises for developers since they
have an object returned that has mutated implicitly without the consumer
being aware. We can have the same performance gain by a clever engine that
figures this sort of thing out itself.


On Sun, Feb 15, 2015 at 4:13 PM, joe joe...@gmail.com wrote:

 Again, where does this mutation occur?  The spec shouldn't allow any such
 thing to begin with; it should mandate exactly what my compiler does: as
 soon as .next returns, copy .value into the loop variable.  The developer
 shouldn't have any access to the return value from within the loop at all;
 if he does, that should (ideally) be considered a violation of the standard.

 On Sun, Feb 15, 2015 at 8:09 AM, Kevin Smith zenpars...@gmail.com wrote:

 When I can get more sound abstractions for no additional cost
 (eventually) I'd rather not introduce implicit mutable state into the
 application. Developers won't be aware of it being mutating and the whole
 notion of a mutating-at-a-later-point return value is very error-prone in
 my opinion.


 Right. Mutating the returned object isn't really tenable from a usability
 point of view.


 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss



___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Subject: Performance of iterator .next() as specified

2015-02-15 Thread joe
On Sun, Feb 15, 2015 at 7:43 AM, Benjamin (Inglor) Gruenbaum 
ing...@gmail.com wrote:

 This is actually exactly the kind of slow code Katelyn was talking about.
 Also, you probably meant `set[Symbol.iterator]()` and `for... of`.


You are correct.  I haven't switched to the 'of' syntax yet (need to do
that).



 What Katelyn is talking about is optimizing .next in the example code to
 not return a new object but to return the same one every time with
 different values filled in. In order to optimize that with your transpiler
 you'd need to implement your own `Set` and `Map` because like Katelyn
 correctly noted `Set` and `Map` do not expose a fast way (in current
 implementations) to iterate them at the moment - at least until engines
 optimize them


I did implement my own, yes.




 Katelyn is arguing it would be useful to allow the implementation to
 return the same instance and I'm arguing the reason it's slow is because
 it's benchmarked against a slow implementation that was not optimized yet
 but can easily be - just like Katelyn noted as LuaJIT does.


I may have misunderstood; it sounded to me like the two of you were
agreeing that JS VMs won't be doing this anytime soon.





 When I can get more sound abstractions for no additional cost (eventually)
 I'd rather not introduce implicit mutable state into the application.
 Developers won't be aware of it being mutating and the whole notion of a
 mutating-at-a-later-point return value is very error-prone in my opinion.


Exactly how would developers mutate the return object in the first place?
And frankly, I don't see how you can care so little about a major,
show-stopping issue such as this.  JS performance has gotten to the point
where people like me write *CAD software* in it.  Usable iterators are
important for such things.

Frankly, I find this sudden embrace of good coding practices odd in a
language that practically sets the floor for how horrendously mutable a
dynamic runtime language can get.



 On Sun, Feb 15, 2015 at 3:35 PM, joe joe...@gmail.com wrote:



 On Sun, Feb 15, 2015 at 7:16 AM, Benjamin (Inglor) Gruenbaum 
 ing...@gmail.com wrote:


 This is something that can be solved at the VM level. VMs perform much
 much smarter optimizations than this already. There is no reason to
 sacrifice code correctness and the principle of least astonishment in order
 to get acceptable performance. Benchmarking against proof of concept
 implementations is counter-productive in my opinion. The engines are
 already 'allowed' to use the same object when there is no observable
 difference. Even if we allow this 'optimization' it will take the engines
 as much time to implement it so there is no gain from this anyway.

 __


 Is 60,000 lines of source code a good enough proof of concept for you?

 I don't see what the problem is.  My transpiler generators the following
 ES5 code:

 //for (var item in set)

 var iter = obj.iterator();
 while (1) {
var ret = obj.next();

if (ret.done) break;
var item = ret.value;
...loop body
 }

 It works quite well.  You may be right about the VM vendors, however.
 This requirement basically makes JS useless for anything other than minor
 scripting tasks.  The VM people may not have any choice but to optimize it.

 Joe


 On Sun, Feb 15, 2015 at 3:35 PM, joe joe...@gmail.com wrote:



 On Sun, Feb 15, 2015 at 7:16 AM, Benjamin (Inglor) Gruenbaum 
 ing...@gmail.com wrote:


 This is something that can be solved at the VM level. VMs perform much
 much smarter optimizations than this already. There is no reason to
 sacrifice code correctness and the principle of least astonishment in order
 to get acceptable performance. Benchmarking against proof of concept
 implementations is counter-productive in my opinion. The engines are
 already 'allowed' to use the same object when there is no observable
 difference. Even if we allow this 'optimization' it will take the engines
 as much time to implement it so there is no gain from this anyway.

 __


 Is 60,000 lines of source code a good enough proof of concept for you?

 I don't see what the problem is.  My transpiler generators the following
 ES5 code:

 //for (var item in set)

 var iter = obj.iterator();
 while (1) {
var ret = obj.next();

if (ret.done) break;
var item = ret.value;
...loop body
 }

 It works quite well.  You may be right about the VM vendors, however.
 This requirement basically makes JS useless for anything other than minor
 scripting tasks.  The VM people may not have any choice but to optimize it.

 Joe



___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Subject: Performance of iterator .next() as specified

2015-02-15 Thread joe
Sorry about that, I think I'm unconsciously substituting return value of
.next for .next.value.  I am talking about reusing the return object,
yes; for some reason in my head, return object of .next refers to
.next(), while return value of .next refers to .next().value.
Communication error on my part.



On Sun, Feb 15, 2015 at 8:19 AM, Benjamin (Inglor) Gruenbaum 
ing...@gmail.com wrote:

 Joe, I don't think we're having the same discussion.

 Again, this is about the issue Katelyn raised about the return value of
 `.next`.

 Katelyn suggested that the return value of a `.next` call in the iteration
 protocol - an object of the form `{value: value, done: boolean}` should be
 allowed to be reused between calls - so an iterator can return _the same_
 object without allocating a new one.

 I argue (and from what I understand Kevin agrees with me) that allowing
 this is error prone and might cause surprises for developers since they
 have an object returned that has mutated implicitly without the consumer
 being aware. We can have the same performance gain by a clever engine that
 figures this sort of thing out itself.


 On Sun, Feb 15, 2015 at 4:13 PM, joe joe...@gmail.com wrote:

 Again, where does this mutation occur?  The spec shouldn't allow any such
 thing to begin with; it should mandate exactly what my compiler does: as
 soon as .next returns, copy .value into the loop variable.  The developer
 shouldn't have any access to the return value from within the loop at all;
 if he does, that should (ideally) be considered a violation of the standard.

 On Sun, Feb 15, 2015 at 8:09 AM, Kevin Smith zenpars...@gmail.com
 wrote:

 When I can get more sound abstractions for no additional cost
 (eventually) I'd rather not introduce implicit mutable state into the
 application. Developers won't be aware of it being mutating and the whole
 notion of a mutating-at-a-later-point return value is very error-prone in
 my opinion.


 Right. Mutating the returned object isn't really tenable from a
 usability point of view.


 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss




___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: extends null

2015-02-15 Thread Erik Arvidsson
Making it a dynamic error at class definition time to extend null would
work but the motivation for not doing that was that someone might want to
create a class that has a {__proto__: null} prototype. Personally, I would
be fine with saying that this case is so rare that it would be better to
have that dynamic error at class definition time.

On Sat Feb 14 2015 at 4:52:40 PM Mark S. Miller erig...@google.com wrote:

 On Sat, Feb 14, 2015 at 1:45 PM, Axel Rauschmayer a...@rauschma.de
 wrote:


 On 14 Feb 2015, at 22:26, Mark S. Miller erig...@google.com wrote:

 On Sat, Feb 14, 2015 at 1:21 PM, Axel Rauschmayer a...@rauschma.de
 wrote:

 But it’s not an error! Either of the following two classes fail later,
 when you instantiate them, but not right away.

 ```js
 const X = null;
 class C extends X {}

 class D extends null {}
 ```


 I didn't mean to imply an early error. The extends X can only produce a
 dynamic error, so I'm arguing that extends null should do the same.


 When I say “early”, I don’t mean “static”, I mean: dynamically, when the
 class definition is evaluated, not later when the class is instantiated via
 `new`.

 I’m not seeing a dynamic error in the spec when the `extends` clause is
 null (step 6e):
 https://people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-classdefinitionevaluation



 That's a good suggestion. AFAICT, it would be an improvement. I don't see
 any downside.

 Allen?





 Or dynamically switching from derived to base (but you seem to be
 saying that doing this dynamically is not a good idea).


 Dynamically switching from derived to base does not work, because our
 super semantics depends statically on the difference.


 Ah, checked statically, I wasn’t aware! Hadn’t found the check
 beforehand. Searched some more and it is indeed there, in 14.5.1.

 --
 Dr. Axel Rauschmayer
 a...@rauschma.de
 rauschma.de






 --
 Cheers,
 --MarkM
  ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: extends null

2015-02-15 Thread Kevin Smith


 Interesting. I have never seen this pattern and don’t see what it could be
 good for. Thus, a dynamic error at class definition time sounds good to me.


The purpose would be defining a class whose instances don't have
Object.prototype on their prototype chain.  If extends null doesn't work,
then I think you'd have to do something like this to achieve the same?

function NullBase() {}
NullBase.prototype = Object.create(null);

class C extends NullBase {}
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: extends null

2015-02-15 Thread Mark S. Miller
On Sun, Feb 15, 2015 at 11:01 AM, Kevin Smith zenpars...@gmail.com wrote:


 Interesting. I have never seen this pattern and don’t see what it could
 be good for. Thus, a dynamic error at class definition time sounds good to
 me.


 The purpose would be defining a class whose instances don't have
 Object.prototype on their prototype chain.  If extends null doesn't work,
 then I think you'd have to do something like this to achieve the same?

 function NullBase() {}
 NullBase.prototype = Object.create(null);

 class C extends NullBase {}


That still wouldn't work at runtime because of the super semantics of C as
a derived class. Instead


class C {}

C.prototype.__proto__ = null;

Yes, it is ugly, but it is an odd case, so still obeys Kay's dictum:


Simple things should be simple. Complex things should be possible
--Alan Kay





-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: extends null

2015-02-15 Thread Jordan Harband
Rather than making extends null alone a runtime error at class evaluation
time, is there a reason not to instead, make only a reference to super in
the constructor of a class that extends null be a runtime error at class
evaluation time?

On Sun, Feb 15, 2015 at 11:12 AM, Mark S. Miller erig...@google.com wrote:



 On Sun, Feb 15, 2015 at 11:01 AM, Kevin Smith zenpars...@gmail.com
 wrote:


 Interesting. I have never seen this pattern and don’t see what it could
 be good for. Thus, a dynamic error at class definition time sounds good to
 me.


 The purpose would be defining a class whose instances don't have
 Object.prototype on their prototype chain.  If extends null doesn't work,
 then I think you'd have to do something like this to achieve the same?

 function NullBase() {}
 NullBase.prototype = Object.create(null);

 class C extends NullBase {}


 That still wouldn't work at runtime because of the super semantics of C as
 a derived class. Instead


 class C {}

 C.prototype.__proto__ = null;

 Yes, it is ugly, but it is an odd case, so still obeys Kay's dictum:


 Simple things should be simple. Complex things should be possible
 --Alan Kay





 --
 Cheers,
 --MarkM

 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: extends null

2015-02-15 Thread Axel Rauschmayer
 Making it a dynamic error at class definition time to extend null would work 
 but the motivation for not doing that was that someone might want to create a 
 class that has a {__proto__: null} prototype. Personally, I would be fine 
 with saying that this case is so rare that it would be better to have that 
 dynamic error at class definition time.

Interesting. I have never seen this pattern and don’t see what it could be good 
for. Thus, a dynamic error at class definition time sounds good to me.

-- 
Dr. Axel Rauschmayer
a...@rauschma.de
rauschma.de



___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Proposal: No LineTerminator should be allowed between {CallExpression, MemberExpression} TemplateLiteral

2015-02-15 Thread Shinji Ikari
The difference is the uncommon delimiter of the argument lists. If the
template literal must be surrounded by a pair of parentheses it will become
more visually significant. Since it's not, I think not allowing the line
terminator is reasonable.

On Sat, Feb 14, 2015 at 1:41 PM, Shinji Ikari ikariena...@gmail.com wrote:

 Ah yes! I will resend.

 On Fri, Feb 13, 2015 at 20:54 Kevin Smith zenpars...@gmail.com wrote:

 Hey there!  Did you mean to reply to the list?

 On Fri, Feb 13, 2015 at 11:53 PM, Shinji Ikari ikariena...@gmail.com
 wrote:

 The difference is the uncommon delimiter of the argument lists. If the
 template literal must be surrounded by a pair of parentheses it will become
 more visually significant. Since it's not, I think not allowing the line
 terminator is reasonable.

 On Fri, Feb 13, 2015 at 20:29 Kevin Smith zenpars...@gmail.com wrote:


 I propose we add a [No LineTerminator here] between CallExpression/
 MemberExpression and TemplateLiteral.


 This would be inconsistent, since there are no such restrictions
 between member expression or call expression components otherwise.  For
 example, in:

 foo
 (bar)

 and

 foo
 [bar]

 there is no semicolon insertion.



___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Suggestion: for-of-and loops

2015-02-15 Thread Brendan Eich

Kevin Smith wrote:


Have you tried writing a combinator which does exactly that? Take a 
look at zip in python.




Right -- we don't add new syntax lightly, we'd need to see zip used a 
lot, and at some irreducible-without-special-form overhead.


/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: extends null

2015-02-15 Thread Marius Gundersen
 The purpose would be defining a class whose instances don't have
Object.prototype on their prototype chain.  If extends null doesn't work,
then I think you'd have to do something like this to achieve the same?

 function NullBase() {}
 NullBase.prototype = Object.create(null);

 class C extends NullBase {}


Can't this be solved by returning a null object from the constructor?

```js
class Null{
  constructor() {
return Object.create(null);
}
}

class MyClass extends Null{

}
let foo = new MyClass();
foo.toString() //ReferenceError
```

Marius Gundersen
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss