Re: generators vs forEach

2013-07-16 Thread Bruno Jouhier
I thought about yield* but it was not available at the time I wrote this.
But it does not fit the bill because it deals with the synchonous part of
the generator dance, not the async part. My run loop is if a bit more than
the yield* loop (but not much more). The differences are the tests that
deal with the PENDING case (
https://github.com/bjouhier/galaxy/blob/master/lib/galaxy.js lines 83 and
88).

I'm not using Q. I wanted to have minimal runtime overhead so I designed it
so that it does not allocate any extra objects. It's all done with a simple
loop.


2013/7/16 Ron Buckton rbuck...@chronicles.org

  I assume you are referring to something like Q.async/Q.spawn to turn the
 generator into an async function using promises?


 Sent from my Windows Phone
  --
 From: Ron Buckton rbuck...@chronicles.org
 Sent: 7/15/2013 5:02 PM
 To: Bruno Jouhier bjouh...@gmail.com; es-discusses-discuss@mozilla.org
 Subject: RE: generators vs forEach

   Bruno, wouldn't yield* work here to delegate the inner yields?

 Sent from my Windows Phone
  --
 From: Bruno Jouhier bjouh...@gmail.com
 Sent: 7/15/2013 4:12 PM
 To: es-discuss es-discuss@mozilla.org
 Subject: Re: generators vs forEach

   There is no need to CPS transform functions and there is no need for
 deferred functions either. It can all be done with today's generators and a
 little helper library.

  With the C# async/await notation:

- The yield keyword is your await keyword.
- The little * in function* is your async keyword.

   With this you can write:

 function* asyncEach(array, fn) {
for (var i = 0; i  array.length; i++) yield fn(array[i], i);
 }

  and you can call it as:

  function* myFunc(array) {
yield asyncEach(array, function*(elt, i) {
  var foo = yield asyncBar(elt);
  // more ...
   })
 }

  Note that there is *no* helper API in all these async functions that
 call other async functions; The helper API is only needed to interface this
 with the classical callback world: at the very bottom of the stack when you
 call low level callbacks-based I/O functions, and at the top of the stack
 when the event loop runs one of your generator functions.

  The trick is that you need a clever run function to do the little
 yield/next dance with generator functions that call other generator
 functions.

  I've implemented this in
 https://github.com/bjouhier/galaxy/blob/master/lib/galaxy.js (the run and
 invoke functions)

  The only thing I don't like about it is the awkward syntax:

- yield precedence does not work well
- yield is prefix, which does not chain well
- and yield is heavy anyway

 In short, this is a hack to get going but I'm still waiting for the full
 concurrency proposal and its awesome ! syntax.

 Bruno

   Consider the following:
 
function* yieldEach(array){
  array.forEach(n = {
yield n;
  });
}
 
  In order for this to work, not only does `yieldEach` have to be
 suspended for the inner yield, but forEach does as well. That means CPS
 transforming functions based on whether they call a yielding function.


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


Re: Array.prototype.find() (and probably findIndex()) compatibility hazard

2013-07-16 Thread Till Schneidereit
I forgot to follow up on this: the issue in Asana was fixed on their side
last week.

We haven't received any other reports of sites these methods are causing
issues for, so it's looking pretty good so far.


On Fri, Jul 5, 2013 at 8:38 PM, Till Schneidereit t...@tillschneidereit.net
 wrote:




 On Fri, Jul 5, 2013 at 6:53 PM, Rick Waldron waldron.r...@gmail.comwrote:




 On Thu, Jul 4, 2013 at 8:13 PM, Till Schneidereit 
 t...@tillschneidereit.net wrote:

 Just as with the recent addition of Array.prototype.values(), we're
 running into problems with Array.prototype.find()[1].

 Asana uses an internal framework called Luna that contains an
 IIterable. This defines[2][3], among others, `find` and `findIndex`
 functions with signatures that aren't compatible with the ones specified in
 ES6. That causes the entire application to not work. At all.


 I'll try contacting Asana in the hope of them fixing the issue, but
 this'll probably not be the last issue with `find`.



 [1]: https://bugzilla.mozilla.org/show_bug.cgi?id=890070
 [2]:
 https://d3ki9tyy5l5ruj.cloudfront.net/prod/build/bundles/5e40e508ea86bea48248afec47fb23f8f1100243/apps/asana/bundle.js?cb=1372896568000,
 lines 3030 - 3044
 [3]: https://gist.github.com/anonymous/84cde557147d24a2 (in case
 the original link changes)




 Thanks for the report!

 I'm also seeing:
 - filter
 - forEach
 - indexOf
 - join
 - map
 - reduce

 (From L3024-3074)

 It appears that an IIterable is used to create the IVector, which then
 has its patchClass method called with (built-in) Array (L3205). The
 patchClass operation is then extending the Array.prototype with all of the
 custom methods. I've reduced it from the provided code:
 https://gist.github.com/rwldrn/2864ff4b3f804005f370


 Ah, great, thanks for doing that! The reduced version confirms what I
 thought was going on: `patchClass`, `patchInstance` and `addToClass` all
 only add the given function to the given target if a same-named function
 doesn't already exist. As the other potentially-replaces functions all
 predate the library, their semantics match.



 I'm confident this can be fixed internally with little to no problem
 (assuming they have adequate tests written to support their codebase)


 I very much agree, yes. We only had this in Nightly builds for about a
 week now, but it's somewhat reassuring that, as of yet, this is the only
 issue we're aware of with `find` and `findIndex`.


 till



  Rick




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


Re: Array.prototype.find() (and probably findIndex()) compatibility hazard

2013-07-16 Thread Rick Waldron
On Tue, Jul 16, 2013 at 5:39 AM, Till Schneidereit 
t...@tillschneidereit.net wrote:

 I forgot to follow up on this: the issue in Asana was fixed on their side
 last week.

 We haven't received any other reports of sites these methods are causing
 issues for, so it's looking pretty good so far.



Great news! Thanks for the update :)

Rick



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


Re: How primitive are Symbols? Bignums? etc

2013-07-16 Thread Allen Wirfs-Brock

On Jul 15, 2013, at 10:30 PM, Brendan Eich wrote:

 Axel Rauschmayer wrote:
 The (x === Object(x)) test evaluates to true for value objects in this 
 proposal, though. This may break code looking for primitives but we need 
 to see what such code expects. Is it filtering out the legacy typeof-result 
 primitives (plus null), trying to find values for which typeof currently 
 returns object or function? If so, I don't see a problem: int64, 
 bignum, etc. are not legacy primitives. Is this test looking for objects 
 that are their own wrappers? Again all is well, unless mutable wrapper is 
 assumed -- but that's not safe in the ES5 era to assume, anyway.
 
 The most frequent use case I’ve encountered: does the value have a prototype 
 (i.e., will Object.getPrototypeOf() work)?
 
 I’m assuming that value objects will have a prototype, accessible via 
 Object.getPrototypeOf (?)
 
 Yes, they are after all value objects :-P.
 
 js Object.getPrototypeOf(0UL)
 0UL
 

In the latest spec. draft, Object.getPrototypeOf(new Symbol) returns null 
because that is what the [[GetInheritance]] MOP operation produces for exotic 
symbol objects. That's because symbols symbols aren't supposed to have any 
observable properties.

[[GetInhertance]] would do something else for value objects that actually 
exposed inherited properties.

Allen 



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


Re: How primitive are Symbols? Bignums? etc

2013-07-16 Thread Brendan Eich

Allen Wirfs-Brock wrote:

On Jul 15, 2013, at 10:30 PM, Brendan Eich wrote:

Axel Rauschmayer wrote:

The (x === Object(x)) test evaluates to true for value objects in this proposal, though. This may break code looking for 
primitives but we need to see what such code expects. Is it filtering out the legacy typeof-result primitives (plus 
null), trying to find values for which typeof currently returns object or function? If so, I 
don't see a problem: int64, bignum, etc. are not legacy primitives. Is this test looking for objects that are their own wrappers? 
Again all is well, unless mutable wrapper is assumed -- but that's not safe in the ES5 era to assume, anyway.

The most frequent use case I’ve encountered: does the value have a prototype 
(i.e., will Object.getPrototypeOf() work)?

I’m assuming that value objects will have a prototype, accessible via 
Object.getPrototypeOf (?)

Yes, they are after all value objects :-P.

js  Object.getPrototypeOf(0UL)
0UL



In the latest spec. draft, Object.getPrototypeOf(new Symbol) returns null 
because that is what the [[GetInheritance]] MOP operation produces for exotic 
symbol objects. That's because symbols symbols aren't supposed to have any 
observable properties.

[[GetInhertance]] would do something else for value objects that actually 
exposed inherited properties.


As it should:

js Object.getPrototypeOf(0UL) === uint64.prototype
true

for toString and valueOf at least.

/be

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


Re: How primitive are Symbols? Bignums? etc

2013-07-16 Thread Allen Wirfs-Brock

On Jul 16, 2013, at 4:34 AM, Andreas Rossberg wrote:

 On 15 July 2013 19:44, Allen Wirfs-Brock al...@wirfs-brock.com wrote:
 The is primarily an internal spec. change.  Many internal operations within 
 the spec. require objects as parameters.  This required inserting inserting 
 explicit guards in p=many places within the specification and remembering to 
 include them in new algorithms. At the March meeting you objected to the 
 two pages of specification required to define Symbols as exotic objects.  
 It turned out that those two pages were fair simpler and less intrusive than 
 the all the individual spec. changes (and ongoing additions) that were 
 needed to support symbols as primitive values.
 
 I'm afraid I still don't see how this is the case (the draft diffs are
 not particularly easy to read). Almost everything should be handled by
 ToObject creating a wrapper object in the traditional places,
 shouldn't it? What are the contexts where (a) an object is required,
 but (b) a symbol would behave differently from existing primitives?
 
 
 User visible semantics comes down to whether or not there is a Symbol 
 wrapper object. As far as I can tell, tell from the notes, there was no 
 consensus WRT Symbol wrappers record in March and when I tried to convert to 
 Symbols as primitive values in the spec. I don't provide such wrappers.  
 Instead, I made ToObject throw for symbols values.
 
 OK, that might explain the difficulty you faced. My understanding of
 the March agreement certainly was that there is a wrapper object,
 consistent with other primitive types. And I'm pretty sure that that
 makes the spec quite simple and regular.

Yes, wrappers would make it easier, but my take away from the meeting and 
subsequent discussion was that we didn't want to add any more observable 
wrappers. 
 
 
 We really should avoid adding new  primitive types and wrapper objects.  
 Value objects are the way to go, starting with Symbol.
 
 I'd argue for the contrary, namely that we should avoid artificially
 cramping more inappropriate concepts into the notion of 'object'!
 These are not objects by any useful definition of the word, despite
 the MOP being rich enough to support them as degenerate cases.

Clearly I disagree. In ES and other polymorphic object-based languages, objects 
are really the basis for uniformity of references.  Any abstraction can be 
represented as an object and any operation can be manifested as method 
invocations upon an object. 

It is the ES primitive types that introduce non-uniformity that either needs to 
be special cased or partially hidden behind hacks such as automatic conversion 
to wrapper objects. Clearly at an implementation level you want to have 
optimized representations of certain kinds of entities.  You can get there two 
different ways.  You can expose the optimized representation as primitive 
types that requires user level special casing or you can uniformly expose 
everything as an object and let the implementation opaquely use special case 
representations where it suits it.

It seems clear to me, that if  you want to support an open ended set of new 
abstractions you need to go the uniform objects route.   We're stuck with 
numbers, strings, and booleans and their corresponding wrappers. We don't need 
more special cases at that level.

 
 
 I'd be interested in hearing how this makes any difference to you from an 
 implementation perspective.  Even when symbols are specified as exotic 
 objects you can still encode them as immediate values, just like you would a 
 SmallInteger in Smalltalk. It's only when actual object MOP operations are 
 applied to them that you should have to do any special casing but these are 
 generally the same situations where you would have to auto-wrap primitive 
 values.
 
 The difference is that with real primitives + wrapper objects every
 respective operation has a single place where it does the ToObject
 conversion (which exists already), and downstream you can easily make
 it an invariant that what you've got is an ordinary object with an
 ordinary object representation. No special casing required.
 
 If, on the other hand, you make new primitives pseudo-objects, but
 still want to represent them efficiently, then all parts that deal
 with objects now also have to deal with those denormal
 representations. You say only actual MOP operations, but surely
 there are several times more occurrences of those than of ToObject. It
 involves the majority of language operations, and in contemporary
 implementations, every one of them potentially has a dozen or more
 possible implementations.

Sounds like your are concerned about special casing MOP dispatches on 
primitives representations.  A good concern.  However, I don't actually see 
much benefit of a primitive non-dispatchable representation for symbols and if 
you do, you could still hide it in ToObject.  Nothing saying you can't have 
internal wrapper objects and be careful not to 

Re: generators vs forEach

2013-07-16 Thread Claus Reinke

   // this doesn't work
   function* generator(){
   [1,2,3].forEach( function(x){ yield x } )
   }


This would make generators deep, violating the non-interleaving assumptions
of intermediate callers on the call stack. This is why we accepted
generators only on condition that they be shallow. We knew at the time that
this privileges built-in control structures over user defined ones. The
alternative would have been to omit generators completely. We agree that
shallow generators were worth it, despite this non-uniformity.


While I understand the compromise, and the wish to get in some form
of generators anyway, the discrimination against user-defined control
structures troubles me deeply. It introduces a new language construct
that defies abstraction. It means that we can no longer use functional
abstraction freely, but have to worry about interactions with generators.

For the specific case of forEach et al, another way to avoid intermediate
stack frames would be guaranteed inlining. If we always inline .forEach 
before execution, then specialize the resulting code wrt the callback,

any yields in the callback would be directly in the caller. Consider this
chain of code transformations:

   // inline forEach; this still doesn't work
   function* generator(){
   (function forEach(arr,cb) {
   for (var i=0; iarr.length; i++) cb(arr[i]);
   })([1,2,3], function(x){ yield x } );
   }

   // instantiate inlined forEach; still doesn't work
   function* generator(){
   let arr = [1,2,3];
   let cb = function(x){ yield x };
   for (var i=0; iarr.length; i++) cb(arr[i]);
   }

   // inline cb; still doesn't work
   function* generator(){
   let arr = [1,2,3];
   for (var i=0; iarr.length; i++) (function(x){ yield x})(arr[i]);
   }

   // instantiate inlined cb; this should work
   function* generator(){
   let arr = [1,2,3];
   for (var i=0; iarr.length; i++) yield arr[i];
   }

If such inlining and instantiating functions in ES6 changes the validity 
of code, then the opposite path -building abstractions from concrete

code examples- is also affected. I find that worrying.

The final form of the code can be handled with shallow generators,
and it should be semantically equivalent to the initial form (just
function application and variable instantiation in between). So why
shouldn't both forms be valid and doable without overcomplicating
the shallow generator ideal?

In pragmatic terms, perhaps introducing inline annotations for 
operations like .forEach and for their callback parameters could avoid 
nested stack frames her without forcing user-side code duplication. 
Such annotation-enforced inlining should also help with performance 
of .forEach et al (currently behind for-loops).


[in conventional pre-compiling FPL implementations, such worker/
wrapper staging plus inlining is done at compile time (stage recursive 
higher-order function into non-recursive wrapper and recursive but 
not higher-order worker; inline wrapper to instantiate the functional 
parameters in the nested worker; finally apply standard optimizer); 

it is an easy way to avoid deoptimizations caused by higher-order 
parameters interfering with code analysis; provided the library

author helps with code staging and inline annotations ]

Put another way, shallow generators are equivalent to a local cps 
transform of the generator function itself. Deep generators would 
require the equivalent of CPS transforming the world -- violating 
the stateful assumptions of existing code.


FYI:

I'm not sure what you mean by violating the stateful assumptions
but there is an even more local transform than that for ES6 generators:
writing code in monadic style always captures the local continuation
only. That allows for generator monads that compose those local
continuations back together. 

An example of such a generator monad can be found here (using a 
list of steps for simplicity; code is TypeScript v0.9, to make use of

ES6 classes with class-side inheritance and arrow functions)

   https://gist.github.com/clausreinke/5984869#file-monadic-ts-L91-L125

with example code (using user-defined forOf) at

   https://gist.github.com/clausreinke/5984869#file-monadic-ts-L492-L529

This differs from ES6 generators in using a functional API (next returns
{done,value,next}) and in building on expressions and user-defined
control-flow operations instead of statement blocks and built-in
control-flow structures. Still, this style does seem to allow more reuse
of existing ES5 array operations than ES6 generators will, as this
small example demonstrates:

   console.log(\n// mixing yield with higher-order array ops (prefix ^));
   var generator4 = ()= [1,2,3].map( x= G.yield(x) )
.reduce( (x,y)= x.then( _= y ), 
G.of(undefined) ) ;
   MonadId.forOf( generator4(), y= (console.log(^ +y), MonadId.of(y)) );

append example to the end of that gist, execute with tsc -e (TS v0.9 
required, 

Re: generators vs forEach

2013-07-16 Thread Brendan Eich

Mark S. Miller wrote:
On Tue, Jul 16, 2013 at 10:54 AM, Claus Reinke 
claus.rei...@talk21.com mailto:claus.rei...@talk21.com wrote:


   // this doesn't work
   function* generator(){
   [1,2,3].forEach( function(x){ yield x } )

   }

This would make generators deep, violating the
non-interleaving assumptions
of intermediate callers on the call stack. This is why we accepted
generators only on condition that they be shallow. We knew at
the time that
this privileges built-in control structures over user defined
ones. The
alternative would have been to omit generators completely. We
agree that
shallow generators were worth it, despite this non-uniformity.


While I understand the compromise, and the wish to get in some form
of generators anyway, the discrimination against user-defined control
structures troubles me deeply.


Troubles me too. As of ES6 the only possible alternative would be to 
remove generators from the language. I can't see that happening.


That would be somewhere between making the perfect the enemy of the 
good and cutting off your nose to spite your face.


If we want call/cc (plus macros to sugar it into usability), there's the 
door -- it ain't in JS outside of Rhino, and (for good reasons you 
adduce) it won't be added.


But we have good use cases for generators, including to implement 
iterators independent of async. programming.


For async we're looking at defer/await for ES7.

This is how living languages evolve. Sorry to preach to the choir (I 
hope :-P).


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


Re: generators vs forEach

2013-07-16 Thread David Bruant

Le 16/07/2013 19:54, Claus Reinke a écrit :

   // this doesn't work
   function* generator(){
   [1,2,3].forEach( function(x){ yield x } )
   }
I have been thinking and with for..of, I can't find a good reason to use 
.forEach instead of for..of.

for..of does what you need here with generators too.

This would make generators deep, violating the non-interleaving 
assumptions

of intermediate callers on the call stack. This is why we accepted
generators only on condition that they be shallow. We knew at the 
time that

this privileges built-in control structures over user defined ones. The
alternative would have been to omit generators completely. We agree that
shallow generators were worth it, despite this non-uniformity.


While I understand the compromise, and the wish to get in some form
of generators anyway, the discrimination against user-defined control
structures troubles me deeply. It introduces a new language construct
that defies abstraction. It means that we can no longer use functional
abstraction freely, but have to worry about interactions with generators.

For the specific case of forEach et al
What do you mean by et al? I don't believe .map, .reduce or .filter 
are any interesting to use alongside generators.


Even if so, for..of can work too and is decently elegant (YMMV):

function* g(){
[1,2,3].map(x = {yield transform(x)})
}

becomes

function* g(){
for(x of [1,2,3]) yield transform(x);
}

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


[Resurrection] Make Function.length Configurable

2013-07-16 Thread Jeremy Martin
This is a resurrection of an earlier proposal from Nathan Wall [1], that
would make Function.length configurable.  The initial proposal was to make
it writable, but configurable instead was suggested by Claude Pache [2].

Nathan's original post [1] does a good job of outlining the motivation, so
I won't reiterate them here.  From what I can gather, making
Function.length configurable seemed to receive a positive response [3] [4]
[5], but the thread apparently died.  Perhaps I just need to find a new API
paradigm, but I run into this issue on a regular basis writing callback
utilities, and would be very interested in seeing this move forward.

For convenience, the Function.length spec from the latest draft [6]:

This is a data property with a value of 1. This property has the attributes
{ [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.


[1] http://www.mail-archive.com/es-discuss@mozilla.org/msg21786.html
[2] http://www.mail-archive.com/es-discuss@mozilla.org/msg21792.html
[3] http://www.mail-archive.com/es-discuss@mozilla.org/msg21793.html
[4] http://www.mail-archive.com/es-discuss@mozilla.org/msg21794.html
[5] http://www.mail-archive.com/es-discuss@mozilla.org/msg21795.html
[6] http://people.mozilla.org/~jorendorff/es6-draft.html#sec-15.3.2.2

Thanks,

-- 
Jeremy Martin
661.312.3853
http://devsmash.com
@jmar777
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: [Resurrection] Make Function.length Configurable

2013-07-16 Thread Jeremy Martin
I referenced Function.length instead of Function#length. Here's the
actually relevant spec [1]:

The value of the length property is an integer that indicates the typical
number of arguments expected by the function. However, the language permits
the function to be invoked with some other number of arguments. The
behaviour of a function when invoked on a number of arguments other than
the number specified by its length property depends on the function. This
property has the attributes { [[Writable]]: false, [[Enumerable]]: false,
[[Configurable]]: false }.


Everything else still applies.  (Hopefully) goes without saying, but the
same should apply to GeneratorFunction instances as well [2].

[1] http://people.mozilla.org/~jorendorff/es6-draft.html#sec-15.3.4.1
[2] http://people.mozilla.org/~jorendorff/es6-draft.html#sec-15.19.3.4

On Tue, Jul 16, 2013 at 3:53 PM, Jeremy Martin jmar...@gmail.com wrote:

 This is a resurrection of an earlier proposal from Nathan Wall [1], that
 would make Function.length configurable.  The initial proposal was to make
 it writable, but configurable instead was suggested by Claude Pache [2].

 Nathan's original post [1] does a good job of outlining the motivation, so
 I won't reiterate them here.  From what I can gather, making
 Function.length configurable seemed to receive a positive response [3] [4]
 [5], but the thread apparently died.  Perhaps I just need to find a new API
 paradigm, but I run into this issue on a regular basis writing callback
 utilities, and would be very interested in seeing this move forward.

 For convenience, the Function.length spec from the latest draft [6]:

 This is a data property with a value of 1. This property has the
 attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]:
 false }.


 [1] http://www.mail-archive.com/es-discuss@mozilla.org/msg21786.html
 [2] http://www.mail-archive.com/es-discuss@mozilla.org/msg21792.html
 [3] http://www.mail-archive.com/es-discuss@mozilla.org/msg21793.html
 [4] http://www.mail-archive.com/es-discuss@mozilla.org/msg21794.html
 [5] http://www.mail-archive.com/es-discuss@mozilla.org/msg21795.html
 [6] http://people.mozilla.org/~jorendorff/es6-draft.html#sec-15.3.2.2

 Thanks,

 --
 Jeremy Martin
 661.312.3853
 http://devsmash.com
 @jmar777




-- 
Jeremy Martin
661.312.3853
http://devsmash.com
@jmar777
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: How primitive are Symbols? Bignums? etc

2013-07-16 Thread Brendan Eich

Allen Wirfs-Brock wrote:

We're stuck with numbers, strings, and booleans and their corresponding 
wrappers. We don't need more special cases at that level.


I should write an apologator 
(http://www-archive.mozilla.org/apology.html) for inflicting primitives 
as non-objects in those ten days in May. Agree they are an 
anti-pattern at this point, not to be imitated by symbol/Symbol (and I 
thought TC39 agreed on this, and no strawman or proposal had both).


For symbols you don't inherently have to have two different 
representations.


Not only do you, or we, not face _a priori_ arguments for symbol and 
Symbol, users do not want.


Yes, it's drawing a line and saying no added special case primitive 
types and no new wrapper objects. Starting with ES6 all new 
abstractions can be conceptualized as objects.
Agreed. Not to dogpile on, but just to apologize for primitives and say 
that they are the exception that proves the rule, not the pattern for 
novelties. See also int64, bignum, etc.


/be

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


Re: Language Negotiation API

2013-07-16 Thread Ian Hickson
On Tue, 16 Jul 2013, Andy Earnshaw wrote:
 
 navigator.language isn't part of any stable specification

It's part of the HTML standard:

   http://whatwg.org/html/#language-preferences

...which is very stable at this point (there's basically no way that part 
of the spec can change in an incompatible fashion, since it's widely 
implemented; the only possible changes are those that approach reality 
more, and those that add features).


 and even the current HTML 5.1 draft doesn't specify that tags should be 
 returned in canonical form.  Do you think it would be a good idea to 
 raise an issue for this?

Fixed. (A change that approaches reality more.)

-- 
Ian Hickson   U+1047E)\._.,--,'``.fL
http://ln.hixie.ch/   U+263A/,   _.. \   _\  ;`._ ,.
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Map etc and [[Call]]

2013-07-16 Thread Erik Arvidsson
All of the new constructors, Map, Set, WeakMap and WeakSet should fail
when called as a function unless `this` already has a certain internal
property, ie [[MapData]]. This is so that sub classing works as
expected.

However, all JS engines that supports Map, Set and WeakMap are future
hostile and they all return a new instance when called as a function.
For example, here is the V8 code:

function MapConstructor() {
  if (%_IsConstructCall()) {
%MapInitialize(this);
  } else {
return new $Map();
  }
}

I understand that fully supporting @@create requires a lot of work but
until then we should at least throw when called as function to allow
us to get out of this mess eventually.

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


Re: Creating your own errors

2013-07-16 Thread Jonas Sicking
On Wed, Jul 10, 2013 at 11:49 PM, Mark S. Miller erig...@google.com wrote:
 Hi Jonas,

 The perpetual hazard with trying to clean things up is, of course, legacy
 compat constraints. Regarding ES itself, many of those on this list
 (including myself) feel oriented about when and where these bite and how
 much, and have successfully navigated through these to many successful
 cleanups. We have also succeeded at not wasting too much time on attractive
 cleanups whose adoption was doomed because of these constraints.

 Regarding DOM, I am certainly less oriented and I suspect at least some
 others on this list are too. In the absence of knowledge, it is tempting to
 imagine the worst and despair of cleaning up anything that is already
 deployed. Could you give a summary -- necessarily subjective which is fine
 -- of how you think about what can and cannot be successfully cleanup up
 here? Thanks.

I think we have the following constraints for exceptions thrown by the DOM:

x instanceof DOMException
This *probably* needs to evaluate to true.

x.code == DOMException.HIERARCHY_REQUEST_ERR
x.code == 3
This definitely needs to evaluate to true for a bunch of older APIs.
This used to be the only way to test what type of exception you had.
For newer exception types we haven't added a code and so .code returns
0. For those APIs you use .name instead, see below. Obviously the
exact constant and number varies with the exception type.

x.name == HierarchyRequestError
This should test true. This should be uncontroversial enough that I
don't think it matters how much dependency there is, right? Obviously
the exact value varies with the exception type.

x.message
This probably needs to contain a human readable error message. This
should be uncontroversial enough that I don't think it matters how
much dependency there is, right?

Object.toString(x)
I *don't* think it's important what this returns. I.e. I would guess
that we can safely subclass DOMException as needed.


I think we have the following constraints for properties that contain
error information in APIs that currently use DOMError
(IDBTransaction.error in the IndexedDB spec for example).

x instanceof DOMError
Probably doesn't matter what this returns.

x.name = AbortError
This should be uncontroversial enough that I don't think it matters
how much dependency there is, right?

x.message
This probably needs to contain a human readable error message. This
should be uncontroversial enough that I don't think it matters how
much dependency there is, right?

Object.toString(x)
Probably doesn't matter what this returns.


I doubt that in either case it matters if these properties live on the
objects themselves, or on the prototype chain.


So all in all, I think we have a lot of room for what to do in both
cases. The only requirements is that exceptions *likely* need to test
true for instanceof DOMException, and that they in some cases need
to have a specific numeric code property.

My recommendation would be to
* Get rid of DOMError and use DOMException in its place
* Add new subclasses for each exception type. I.e. exceptions with
.name == HierarchyRequestError should also test true for instanceof
HierarchyRequestError
* Keep specifying that DOMException is a subclass of Error. This is
already the case, but I wanted to make it clear that this shouldn't
change.

I personally think that the second bullet is a bit silly. But since
that appears to be the convention that ES uses then we should stick
with it.

/ Jonas

 On Wed, Jul 10, 2013 at 8:31 PM, Jonas Sicking jo...@sicking.cc wrote:


 On Jul 10, 2013 3:49 PM, Erik Arvidsson erik.arvids...@gmail.com
 wrote:
 
  Jonas, DOM never throws DOMError. DOMErrors are used for other error
  mechanisms, such as callbacks. [1]

 Indeed. But this is one of the things I'm trying to fix. It seems very
 silly that the DOM defines two classes of error objects. Neither of which
 are following the patterns used by ES.

 / Jonas

 
  The DOM spec does however throw DOMException objects [2]. These are
  instanceof Error (see WebIDL [3])
 
  var ex;
  try {
document.appendChild(document);
  } catch (e) {
ex = e;
  }
  assert(ex instanceof Error);
  assert(ex.contructor === DOMException);
  assert(ex.name === 'HierarchyRequestError');
 
  In Blink DOMException also have a stack property
  assert(stack in ex);
 
  [1] http://dom.spec.whatwg.org/#interface-domerror
  [2] http://dom.spec.whatwg.org/#exception-domexception
  [3]
  http://dev.w3.org/2006/webapi/WebIDL/#es-exception-interface-prototype-object
 
  On Wed, Jul 10, 2013 at 3:02 PM, Jonas Sicking jo...@sicking.cc wrote:
   On Wed, Jul 10, 2013 at 12:52 PM, Domenic Denicola
   dome...@domenicdenicola.com wrote:
   Woah, François, that seems pretty overcomplicated; why not replace
   everything inside the constructor with `this.message = message`? It has 
   the
   same effect in the browsers I've seen. (Also don't forget
   `SomeError.prototype.constructor = SomeError`.)
  
  

Re: Map etc and [[Call]]

2013-07-16 Thread Rick Waldron
On Tue, Jul 16, 2013 at 7:10 PM, Erik Arvidsson erik.arvids...@gmail.comwrote:

 All of the new constructors, Map, Set, WeakMap and WeakSet should fail
 when called as a function unless `this` already has a certain internal
 property, ie [[MapData]]. This is so that sub classing works as
 expected.

 However, all JS engines that supports Map, Set and WeakMap are future
 hostile and they all return a new instance when called as a function.
 For example, here is the V8 code:

 function MapConstructor() {
   if (%_IsConstructCall()) {
 %MapInitialize(this);
   } else {
 return new $Map();
   }
 }

 I understand that fully supporting @@create requires a lot of work but
 until then we should at least throw when called as function to allow
 us to get out of this mess eventually.


It's painful, but I agree. This will prevent a build up of incorrect code
that may hold @@create semantics hostage.

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


Re: generators vs forEach

2013-07-16 Thread Rick Waldron
On Tue, Jul 16, 2013 at 3:45 PM, David Bruant bruan...@gmail.com wrote:

 Le 16/07/2013 19:54, Claus Reinke a écrit :

 // this doesn't work
function* generator(){
[1,2,3].forEach( function(x){ yield x } )
}

 I have been thinking and with for..of, I can't find a good reason to use
 .forEach instead of for..of.
 for..of does what you need here with generators too.



I've been looking at this example and thinking the same thing.
Additionally, I'm curious to know what this would've looked like without
being a contrived example of mis-used yield, considering
Array.prototype.forEach returns undefined and the callback returns
undefined as well (regardless of whether or not user code specifies a
return).

Rick






  This would make generators deep, violating the non-interleaving
 assumptions
 of intermediate callers on the call stack. This is why we accepted
 generators only on condition that they be shallow. We knew at the time
 that
 this privileges built-in control structures over user defined ones. The
 alternative would have been to omit generators completely. We agree that
 shallow generators were worth it, despite this non-uniformity.


 While I understand the compromise, and the wish to get in some form
 of generators anyway, the discrimination against user-defined control
 structures troubles me deeply. It introduces a new language construct
 that defies abstraction. It means that we can no longer use functional
 abstraction freely, but have to worry about interactions with generators.

 For the specific case of forEach et al

 What do you mean by et al? I don't believe .map, .reduce or .filter are
 any interesting to use alongside generators.

 Even if so, for..of can work too and is decently elegant (YMMV):

 function* g(){
 [1,2,3].map(x = {yield transform(x)})
 }

 becomes

 function* g(){
 for(x of [1,2,3]) yield transform(x);
 }

 David

 __**_
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/**listinfo/es-discusshttps://mail.mozilla.org/listinfo/es-discuss

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


Re: Map etc and [[Call]]

2013-07-16 Thread Brendan Eich

Brandon Benvie wrote:

On 7/16/2013 4:10 PM, Erik Arvidsson wrote:

All of the new constructors, Map, Set, WeakMap and WeakSet should fail
when called as a function unless `this` already has a certain internal
property, ie [[MapData]]. This is so that sub classing works as
expected.

However, all JS engines that supports Map, Set and WeakMap are future
hostile and they all return a new instance when called as a function.
For example, here is the V8 code:

function MapConstructor() {
   if (%_IsConstructCall()) {
 %MapInitialize(this);
   } else {
 return new $Map();
   }
}

I understand that fully supporting @@create requires a lot of work but
until then we should at least throw when called as function to allow
us to get out of this mess eventually.



I wonder if the current spec language is a remnant of before @@create 
was added to the spec. It should be possible to detect when the 
constructors are called with a receiver that is not an initializing 
instance and simply create a new instance. Pseudo code:


function Map(...args){
  if (!IsObject(this) || !%HasMapData(this)) {
// got a primitive, the global object, or some random object like 
from `Map.call({})`

return new Map(...args);
  } else if (!%IsInitializedMap(this)) {


Nit: else after return ;-).

More substantive: Mark's suggestion seems better because it throws on 
random wrong this but supports strict calls by unqualified name.


/be

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


Re: Creating your own errors

2013-07-16 Thread Erik Arvidsson
On Tue, Jul 16, 2013 at 4:30 PM, Jonas Sicking jo...@sicking.cc wrote:

 Object.toString(x)

I assume you mean Object.prototype.toString.call(x)

 I *don't* think it's important what this returns. I.e. I would guess
 that we can safely subclass DOMException as needed.


 I think we have the following constraints for properties that contain
 error information in APIs that currently use DOMError
 (IDBTransaction.error in the IndexedDB spec for example).

 x instanceof DOMError
 Probably doesn't matter what this returns.

FWIW, Neither Blink nor WebKit exposes DOMError so this should be safe
to change (on the open web at least).

 x.name = AbortError
 This should be uncontroversial enough that I don't think it matters
 how much dependency there is, right?

 x.message
 This probably needs to contain a human readable error message. This
 should be uncontroversial enough that I don't think it matters how
 much dependency there is, right?

 Object.toString(x)
 Probably doesn't matter what this returns.


 I doubt that in either case it matters if these properties live on the
 objects themselves, or on the prototype chain.


 So all in all, I think we have a lot of room for what to do in both
 cases. The only requirements is that exceptions *likely* need to test
 true for instanceof DOMException, and that they in some cases need
 to have a specific numeric code property.

 My recommendation would be to
 * Get rid of DOMError and use DOMException in its place
 * Add new subclasses for each exception type. I.e. exceptions with
 .name == HierarchyRequestError should also test true for instanceof
 HierarchyRequestError
 * Keep specifying that DOMException is a subclass of Error. This is
 already the case, but I wanted to make it clear that this shouldn't
 change.

 I personally think that the second bullet is a bit silly. But since
 that appears to be the convention that ES uses then we should stick
 with it.

Agreed.

There will be issues here since DOM has throw a SyntaxError, which
means throw a DOMException with the name SyntaxError and the code
DOMException.SYNTAX_ERR so that would mean that we have a naming
conflict since ES already have a SyntaxError constructor.


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


Re: Map etc and [[Call]]

2013-07-16 Thread Brendan Eich

Mark S. Miller wrote:
On Tue, Jul 16, 2013 at 4:56 PM, Brendan Eich bren...@mozilla.com 
mailto:bren...@mozilla.com wrote:


More substantive: Mark's suggestion seems better because it throws
on random wrong this but supports strict calls by unqualified name.


Nit: All calls. The non-coercion of |this| depends only on the 
strictness of the callee, not the caller.


Oh right, and Map, etc. are built-in so as-if-self-hosted-strict in this 
regard.


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


Re: Map etc and [[Call]]

2013-07-16 Thread Allen Wirfs-Brock

On Jul 16, 2013, at 4:10 PM, Erik Arvidsson wrote:

 All of the new constructors, Map, Set, WeakMap and WeakSet should fail
 when called as a function unless `this` already has a certain internal
 property, ie [[MapData]]. This is so that sub classing works as
 expected.

Yes, indeed: 
let m = map();  //I think m is a map
is specified as throwing a TypeError.

To implement it otherwise is diverging from the spec.

Using constructors as callable factories is pretty hostile to subclasses that 
need to do super calls to superclass constructors.  While it is possible to 
carefully code a constructor function that it can work as both a factory and an 
initializer there are plenty of subtleties (and/or performance traps) that are 
likely to trip-up everyday JS programmers.  For that reason, I expect that 
callable constructors that allocate is going to be quickly identified as a ES6 
anti-pattern.  The natural thing to do with ES6 classes is to always use new 
and to code the constructor function to only act as an instance initializer.  
In support of that pattern, Map and friends only allocated when invoked via new.

We will be talking about this some more at next week's TC39 meeting.

 
 However, all JS engines that supports Map, Set and WeakMap are future
 hostile and they all return a new instance when called as a function.
 For example, here is the V8 code:
 
 function MapConstructor() {
  if (%_IsConstructCall()) {
%MapInitialize(this);
  } else {
return new $Map();
  }
 }

Yes, this is wrong because if this was super called from a subclass constructor 
it would return a new Map instance to the subclass constructor rather than 
initializing (if possible) the subclass provided instance as Map. 

I'd don't know much about the V8 self-hosting mechanism, but it looks to me 
like it should be sufficient to code this as:

function MapConstructor() {
   %MapInitialize(this);
}

assuming that %MapInitialize is smart enough to throw on undefined and other 
this values that are not appropriate to initialize as Maps.

 
 I understand that fully supporting @@create requires a lot of work but
 until then we should at least throw when called as function to allow
 us to get out of this mess eventually.

For background here is how new Foo()  is now supposed to work:
let newObj = Foo[@@create]();  //allocate an initialized Foo instance.
Foo.call(newObj); //initialize the newObject
)

It's not very complicated.

Allen


 
 --
 erik
 ___
 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: Map etc and [[Call]]

2013-07-16 Thread Brandon Benvie

On 7/16/2013 4:56 PM, Brendan Eich wrote:
Mark's suggestion seems better because it throws on random wrong this 
but supports strict calls by unqualified name.


I don't think that it'd be nice if `Map()` could throw or not throw 
depending on strictness of the caller. Working around that requires 
something like:


function Map(...args){
  if (this === undefined || this === %CallerGlobal()) {
return new Map(...args);
  } else if (!%HasMapData(this)) {
throw new TypeError(Not a Map);
  } else if (%HasInitializedMapData(this)) {
throw new TypeError(Map is already initialized);
  }
  %MapInitialize(this);
}

(V8's implementation is also incorrect in that it doesn't throw when you 
do `Map.call(new Map)`) (so is SM's)

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


Re: Map etc and [[Call]]

2013-07-16 Thread Brandon Benvie

On 7/16/2013 5:09 PM, Mark S. Miller wrote:
Nit: All calls. The non-coercion of |this| depends only on the 
strictness of the callee, not the caller.


Ah yes, right! Nevermind on the complaint in my last message.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Map etc and [[Call]]

2013-07-16 Thread Erik Arvidsson
I completely agree with you Allen. new-less construct is an anti pattern.

On Tue, Jul 16, 2013 at 5:13 PM, Allen Wirfs-Brock
al...@wirfs-brock.com wrote:
 I understand that fully supporting @@create requires a lot of work but
 until then we should at least throw when called as function to allow
 us to get out of this mess eventually.


 For background here is how new Foo()  is now supposed to work:
 let newObj = Foo[@@create]();  //allocate an initialized Foo instance.
 Foo.call(newObj); //initialize the newObject
 )

 It's not very complicated.

The semantics and the spec are simple but...

...it does require support for symbols, shared symbols between realms,
updates to new without any perf regression.

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


Re: Map etc and [[Call]]

2013-07-16 Thread Allen Wirfs-Brock

On Jul 16, 2013, at 4:41 PM, Mark S. Miller wrote:

 
 
 I like the general idea. But when actually called simply as a function, this 
 would be unpleasant. Understanding that any ES5 behavior will be a compromise 
 to prepare the ground for ES6, I suggest this variant:
 
 function MapConstructor() {
   if (%_IsConstructCall()) {
 %MapInitialize(this);
   } else if (this === void 0) {
this test isn't sufficient is you really want to support constructors as 
callable factories.  Consider an namespace object (or a module) such as:

let ES6 = {Map, WeakMap, Set};
ES6.Map();

 return new $Map();
   } else {
 throw ;
   }
 }
 
 I already have a lot of code that simply calls WeakMap() without saying 
 new. I suspect that others will too by the time they see v8's new built-in 
 WeakMaps.
We need to discourage leaving out the new, rather than trying to preserve the 
small amount (in terms of web scale) of existing code that uses Map/Set/WeakMap 
as callable factories. 

Allen

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


12[__proto__]

2013-07-16 Thread Luke Hoban
All current engines I could try return Number.prototype for:

12[__proto__]

But the new spec says this should be a TypeError.

It's more consistent with the other members of Object.prototype to do an 
implicit ToObject here, and apparently matches existing implementations.  Is it 
intentional that the spec is treating this as a TypeError?

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


RE: 12[__proto__]

2013-07-16 Thread Luke Hoban
 All current engines I could try return Number.prototype for:
   12[__proto__]
 But the new spec says this should be a TypeError.

 What is the relevant part of the new spec?

In B.2.2.1, step #2 throws a TypeError instead of doing a ToObject.

  get Object.prototype.__proto__ 
  The value of the [[Get]] attribute is a built-in function that requires no 
arguments. It performs the following steps:
  1. Let O be the this value.
  2. If Type(O) is not Object, then throw a TypeError exception.
  3. Return the result of calling the [[GetInheritance]] internal method of O.
 
 
 It's more consistent with the other members of Object.prototype to do an 
 implicit ToObject here, and apparently matches existing implementations.  Is 
 it intentional that the spec is treating this as a TypeError?
 
 Luke

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


Re: 12[__proto__]

2013-07-16 Thread Allen Wirfs-Brock

On Jul 16, 2013, at 6:33 PM, Luke Hoban wrote:

 All current engines I could try return Number.prototype for:
  
 12[“__proto__”]
  
 But the new spec says this should be a TypeError.
  
 It’s more consistent with the other members of Object.prototype to do an 
 implicit ToObject here, and apparently matches existing implementations.  Is 
 it intentional that the spec is treating this as a TypeError?
  

Well, it was intentional, but perhaps wrong. As you say, the  set accessor 
probably needs to do a ToObject.  The set accessor probably only needs to do a 
CheckObjectCoercible  followed by an immediate return if the type of this is 
not Object (the wrapper and hence it's modified [[Prototype]] isn't observable, 
so it doesn't actually need to be created).

File a bug, and I'll put the revised algorithms into the ticket.

Allen




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


RE: 12[__proto__]

2013-07-16 Thread Luke Hoban
From: Allen Wirfs-Brock [mailto:al...@wirfs-brock.com]
Sent: Tuesday, July 16, 2013 7:02 PM
To: Luke Hoban
Cc: es-discuss
Subject: Re: 12[__proto__]


On Jul 16, 2013, at 6:33 PM, Luke Hoban wrote:


All current engines I could try return Number.prototype for:

12[__proto__]

But the new spec says this should be a TypeError.

It's more consistent with the other members of Object.prototype to do an 
implicit ToObject here, and apparently matches existing implementations.  Is it 
intentional that the spec is treating this as a TypeError?


Well, it was intentional, but perhaps wrong. As you say, the  set accessor 
probably needs to do a ToObject.  The set accessor probably only needs to do a 
CheckObjectCoercible  followed by an immediate return if the type of this is 
not Object (the wrapper and hence it's modified [[Prototype]] isn't observable, 
so it doesn't actually need to be created).

File a bug, and I'll put the revised algorithms into the ticket.

Opened https://bugs.ecmascript.org/show_bug.cgi?id=1586.

Luke



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


Is Object.watch being standardizied?

2013-07-16 Thread Behrang Saeedzadeh
And if so, where in the spec docs can I read more about it?

Cheers,
Behrang Saeedzadeh
http://www.behrang.org
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Is Object.watch being standardizied?

2013-07-16 Thread Rick Waldron
On Wed, Jul 17, 2013 at 12:14 AM, Behrang Saeedzadeh behran...@gmail.comwrote:

 And if so, where in the spec docs can I read more about it?


No, but Object.observe is:
http://wiki.ecmascript.org/doku.php?id=strawman:observe

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