Re: Are ES Modules garbage collected? If so, do they re-execute on next import?

2020-07-16 Thread Herby Vojčík

On 16. 7. 2020 15:23, Guy Bedford wrote:
Node.js in the CommonJS loader and dynamic loaders like SystemJS have 
supported module unloading for many years by permitting eviction from 
the loader registry. Evicting the full parent tree was the traditional 
reloading workflow in SystemJS, but live binding pushes are also 
permitted in SystemJS as well for this.


I agree there are issues and invariants of course to consider from a 
theoretical perspective, but those are decisions to be made in terms of 
what invariants are valued, and I don't feel they are necessarily 


I understand there may be problems with static imports that are 
statically analyzed, and there "only GC module loader as whole" makes 
sense, but maybe, it would be possible to treat _dynamically loaded_ 
modules different way? Just thinking aloud.


absolute constraints. These decisions should be made based on what is 
best for the JS users and engines. Not that I feel strongly this should 
be a requirement but that it should still be open to consideration.


I'm not sure it was Allen's intention to ban any concept of reloading 
modules when defining the idempotency requirement for the host resolve 
function. Perhaps he could speak to that if he's around.



On Tue, 14 Jul 2020 at 23:05, Mark S. Miller > wrote:


Only a module registry as a whole may be GCed. During the lifetime
of any one module registry, it can only grow. No other solution is
possible.

Btw, I remember being surprised ages ago when the same issue came up
for the Java ClassLoader. A classLoader holds on to all the classes
it ever loaded. Each class holds onto its classLoader. Each instance
holds on to its class. During the lifetime of a classLoader or any
of its classes, the graph of that classLoader and its classes can
only grow new classes. Not until the classLoader and all of its
classes are unreachable at the same time can any of them be
collected. This was equally unfortunate, surprising, and inescapable.



On Tue, Jul 14, 2020 at 10:16 PM #!/JoePea mailto:j...@trusktr.io>> wrote:

How can we ensure that long-running applications (even if
theoretical),
that may load and unload an unlimited number of new modules over
time
(f.e. routes in a web page specified by 3rd parties as time
progresses), not leak memory?

Even if it is theoretical, I don't like the thought of something
that
only ever allocates memory that will never be freed.

Is someone working on a solution for this?


#!/JoePea

On Wed, Jul 1, 2020 at 6:16 AM Mark S. Miller mailto:erig...@gmail.com>> wrote:
 >
 > No, definitely not. The table from specifiers to module
instances is indexed by specifiers. Specifiers are strings, so
this table is not weak. It is not a "cache" in the sense that it
is allowed to drop things. Rather it is a registry of module
instances. Only a registry as a whole can be gc'ed, and which
point that context is no longer around for instantiating or
reinstantiating modules.
 >
 > As you suggest, if it could drop things because of GC that it
would then need to regenerate, that would expose the
non-determinism of gc. That would be a big deal. We carefully
designed WeakMaps so that gc was non-observable. WeakMaps
introduce no observable non-determinism. WeakRefs alone expose
the non-determinism of gc, and are kept well quarantined from
the rest of the language.
 >
 >
 > On Tue, Jun 30, 2020 at 5:42 PM #!/JoePea mailto:j...@trusktr.io>> wrote:
 >>
 >> I am curious: can modules be garbage collected if the
exports are not
 >> references by anything anymore? And if so, will the module be
 >> re-evaluated the next time it is imported?
 >>
 >> I haven't tried an experiment to answer this yet. I'll be
back to post
 >> findings if someone doesn't post an official answer first.
 >>
 >> I'm thinking about code longevity. For example, if we make
 >> long-running web-based applications with many routes and
features (for
 >> sake of example imagine a desktop environment, or a MMORPG
game, with
 >> apps or components that are loaded within the same context).
Over
 >> time, if imports are not collected, then it means we have a
memory
 >> leak.
 >>
 >> Imagine, for example, an infinite-universe MMORPG where you
can land
 >> on different planets where the code for features of a planet are
 >> provided by third parties as ES Modules. I know, this might
not be a
 >> safe idea to import any code into an app, but just imagine
it for sake
 >> of example (imagine we 

Re: Array.prototype.toggle

2020-02-07 Thread Herby Vojčík

On 7. 2. 2020 13:11, Scott Rudiger wrote:
`Array.prototype.filter` seems more versatile (although it doesn't 
mutate the original array) since it removes elements based on a function:


```js
[1, 2, 3, 2, 1].filter(n => n !== 1); // [2, 3, 2]
```


But what if one wants to mutate in-place. Would this work?

  Object.assign(arr, arr.filter(n => n !== 1))

If not, maybe there can be

  aCollection.replaceWith(anIterable)

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


Re: Conditional await, anyone?

2019-10-09 Thread Herby Vojčík

Hi!

First, experiences of this guy 
https://medium.com/@bluepnume/intentionally-unleashing-zalgo-with-promises-ab3f63ead2fd 
seem to refute the problematicity of zalgo.


Second, I actually have the use case of this pattern (though actually 
it's not a use case for a new syntax). In Amber Smalltalk 
(implementation running of top of JS engine), it would immensely help to 
be able to have classical "proxied message send" case, where message 
send is asynchronous in the background. As Amber compiles the code 
itself, you may say "compile it so you simply await every message send", 
but then, code that _must be_ synchronous (callbacks used in external JS 
libs API) will fail. Having two modes is not an option. So I would 
really use the option to have message sends synchronous by default, but 
in the case they _can be_ asynchronous, to be able to let them be that way.


Actually, the paypal guy mentioned in the first paragraph has similar 
case (inter-frame RPC). Using his ZalgoPromise I could compile the 
things like


  ZalgoPromise.resolve(make the message send).then(function (result) ...

Herby

On 8. 10. 2019 22:25, Tab Atkins Jr. wrote:

I'm not sure I understand the intended use-case here.  If the author
knows the function they're calling is async, they can use `await`
normally. If they know it's not async, they can avoid `await`
altogether. If they have no idea whether it's async or not, that means
they just don't understand what the function is returning, which
sounds like a really bad thing that they should fix?  And in that
case, as Gus says, `await?`'s semantics would do some confusing things
to execution order, making the line after the `await?` either run
*before* or *after* the calling code, depending on whether the await'd
value was a promise or not.

~TJ
___
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: [Proposal] Refer to actual value : keyword "itself"

2019-09-06 Thread Herby Vojčík

On 6. 9. 2019 10:34, Cyril Auburtin wrote:

You could currently do
```js
object.child.property /= 5
```

with destructuring:
```js
const {child: {subchild}, child} = state;


Wow, I didn't know I can do that. Nice.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: [Proposal] Optional spreading

2019-08-23 Thread Herby Vojčík

On 23. 8. 2019 16:24, Beknar Askarov wrote:

@Scott Rudiger After thinking more about it.
I would not like to conflict with semantics of optional chaining and 
null coalescing operator.
So in order to not confuse people, maybe introduce two types of optional 
spread operators



1. `?...` - Do not spread if nullish. Note nullish. Else try to spread.
Signature Array: [?...(nullish | Iterable)];
Signature Object: {?...(nullish | object)};

2. `!...` - Do not spread if false. Note FALSE not falsy. Else try to 
spread.


I read

  !...foo

as

  !(...foo)

that is, logical not. I'd tip it already works that way. In which case 
no go, break compat.


Herby


Signature Array: [!...(false | Iterable)];
Signature Object: {!...(false | object)};

I think this can be an option to avoid consfusion


Or add a new one. :-(
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Loose idea on "try import"

2019-03-01 Thread Herby Vojčík

On 1. 3. 2019 18:35, Michał Wadas wrote:

I don't think so, because:

  * Using promises to import module is not always desirable
  * This mechanism doesn't impact ability to statically analyze modules
if ifs are excluded - it can only increase resolution time.


Yeah, if 'if's are excluded. That version with those ifs was what was 
concerning. That actually needs runtime to do the work. I suppose until 
it doesn't need the runtime, it's all ok.




On Fri, Mar 1, 2019 at 1:56 PM Herby Vojčík <mailto:he...@mailbox.sk>> wrote:


On 1. 3. 2019 12:04, Michał Wadas wrote:
 > Syntax:
 >
 > try import fs from 'fs'
 >     else import fs from 'fs-polyfill'
 >     else import fs from 'another-fs-polyfill'
 >     else do nothing; // Not sure about syntax
 >
 >
 > try import {watchDirectory} from 'fs'
 >     else import {watchDirectory} from 'fs-polyfill'
 >     else if(process.os === 'ExoticSystem') import
{watchDirectory} from
 > 'another-fs-polyfill'
 >     else throw Error('Your OS doesn\'t support watching
directories');

I am not an expert, but afaict ES module system was created to be
statically analysable and this bring uncertainity.

For that probably dynamic import() is there; and your usage should
await
for a promise that tries to load one then the other etc.

Herby

 > Usages:
 >
 >   * Optional dependencies
 >   * Polyfills
 >
 > Problems:
 >
 >   * This can prevent loading modules before execution if presence of
 >     modules can't be proved statically
 >   * else-if requires execution before loading module - can be dropped
 >
 >
 > I don't have enough time and knowledge about modules to write actual
 > proposal.



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


Re: Loose idea on "try import"

2019-03-01 Thread Herby Vojčík

On 1. 3. 2019 12:04, Michał Wadas wrote:

Syntax:

try import fs from 'fs'
    else import fs from 'fs-polyfill'
    else import fs from 'another-fs-polyfill'
    else do nothing; // Not sure about syntax


try import {watchDirectory} from 'fs'
    else import {watchDirectory} from 'fs-polyfill'
    else if(process.os === 'ExoticSystem') import {watchDirectory} from 
'another-fs-polyfill'

    else throw Error('Your OS doesn\'t support watching directories');


I am not an expert, but afaict ES module system was created to be 
statically analysable and this bring uncertainity.


For that probably dynamic import() is there; and your usage should await 
for a promise that tries to load one then the other etc.


Herby


Usages:

  * Optional dependencies
  * Polyfills

Problems:

  * This can prevent loading modules before execution if presence of
modules can't be proved statically
  * else-if requires execution before loading module - can be dropped


I don't have enough time and knowledge about modules to write actual 
proposal.

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


Re: Proposal: `Object.isEmpty(value)`

2019-02-14 Thread Herby Vojčík

On 14. 2. 2019 7:54, Jordan Harband wrote:

`Reflect.ownKeys(x || {}).length === 0`?


This seems to reify key list. That gist of the OP is probably to be able 
to be able to tell fast enough if it's empty.


Or are JS engines actually doing this fast (like returning "virtual" 
keys list for which they can tell .length fast and only actually reify 
the keys themselves lazily)?


Herby

On Wed, Feb 13, 2019 at 10:31 PM Isiah Meadows > wrote:


This would be roughly equivalent to `Object.keys(value).length === 0`,
but with a few exceptions:

1. If `value` is either `null` or `undefined`, it gracefully falls
back to `false` instead of throwing an error.
2. It takes enumerable symbols into account, like `Object.assign`.

So more accurately, it returns `false`  if the value is neither `null`
nor `undefined` and has an own, enumerable property, or `true`
otherwise.

It's something I sometimes use when dealing with object-based hash
maps (like what you get from JSON, input attributes). I typically fall
back to the (partially incorrect) `for ... in` with a `hasOwnProperty`
check for string keys, but I'd like to see this as a built-in.

There's also a performance benefit: engines could short-circuit this
for almost everything with almost no type checks. It's also an obvious
candidate to specialize for types.

- If it's not a reference type (object or function), return `true`.
- If it's not a proxy object, or a proxy object that doesn't define
`getPropertyDescriptor` or `ownKeys`, it's often just a memory load,
even with dictionary objects and arrays.
- If it's a proxy object with `ownKeys` and/or
`getOwnPropertyDescriptor`, this is the slow path, but you can still
short-circuit when `ownKeys` returns an empty array.

-

Isiah Meadows
cont...@isiahmeadows.com 
www.isiahmeadows.com 
___
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: Array Comprehensions

2017-04-16 Thread Herby Vojčík

Ryan Birmingham wrote:

Hello all,

I frequently find myself desiring a short array or generator
comprehension syntax. I'm aware that there are functional ways around
use of comprehension syntax, but I personally (at least) love the syntax
in the ES reference
(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Array_comprehensions).

The best previous discussion on this that I found was six years old
(https://esdiscuss.org/topic/array-comprehensions-shorter-syntax) and
answers some of my questions, raising others. That said, I wanted to ask:

  * Why is the Comprehension Syntax in the reference yet not more
standard? It feels almost like a tease.


IIRC, it was discussed here throroughly for ES6 (~2yrs ago?) and it was 
rejected in favour of .map/.filter/arrays fns.



  * How do you usually approach or avoid this issue?
  * Do you think we should look at improving and standardizing the
comprehension syntax?


Thank you all for humoring me,

-Ryan Birmingham

___
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: Cancel Promise pattern (no cancellable promises)

2016-10-31 Thread Herby Vojčík



Herby Vojčík wrote:



Jan-Ivar Bruaroey wrote:

On 10/28/16 8:39 AM, Bergi wrote:

Jan-Ivar Bruaroey wrote:

If you try the fiddle - http://jsfiddle.net/jib1/jz33qs32/ - you'll see
cancelling terminates the chain. If you intersperse non-cancellable
operations, there'd be a delay if cancel is detected during those.


Yes, that's what I mean. Sure, I could use `Promise.race` to get the
cancellation even if the non-cancellable operation resumes, but that's
quite ugly:

Promise.race([
promise()
…chain…,
cancelToken
]).then(callback);

especially when you'll need to nest that pattern.


To be clear, the non-cancellable operation won't "resume" in the face of
a CancelledError. Only if the cancel happened to trigger during one of
the non-cancellable actions would there be a slight delay until that
non-cancellable operation finished (which I consider a feature) and if a
cancellable operation follows it, cancellation will happen at that point.

In someone can't tolerate that, then Promise.race is well-defined to do
exactly what you show, and works in harmony with this pattern. Why
reinvent the wheel?

And you'd Promise.race against the entire chain, so no need to nest this
pattern typically. This is what I mean with focusing on the minimal
use-case. Most people just want us to solve fetch already, so that
expensive network resources can be freed. To get out of the current
inertia, why not define:

fetch (url, { cancelPromise: token })


OTOH, why not to just use Promise.race directly and promote the pattern
of "specify alternate result".
1. This is more general;
2. This allows creating decorators and use them like
shortcutAfter(5000, Promise.reject())(fetch(url))


Well, "shortCircuitAfter" would be probably better name.


now and use this pattern, and leave the more desirable { cancel } name
for whatever future invention we hope will replace it (or annex it if
nothing better materializes)?

.: Jan-Ivar :.


Herby

___
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: Cancel Promise pattern (no cancellable promises)

2016-10-31 Thread Herby Vojčík



Jan-Ivar Bruaroey wrote:

On 10/28/16 8:39 AM, Bergi wrote:

Jan-Ivar Bruaroey wrote:

If you try the fiddle - http://jsfiddle.net/jib1/jz33qs32/ - you'll see
cancelling terminates the chain. If you intersperse non-cancellable
operations, there'd be a delay if cancel is detected during those.


Yes, that's what I mean. Sure, I could use `Promise.race` to get the
cancellation even if the non-cancellable operation resumes, but that's
quite ugly:

Promise.race([
promise()
…chain…,
cancelToken
]).then(callback);

especially when you'll need to nest that pattern.


To be clear, the non-cancellable operation won't "resume" in the face of
a CancelledError. Only if the cancel happened to trigger during one of
the non-cancellable actions would there be a slight delay until that
non-cancellable operation finished (which I consider a feature) and if a
cancellable operation follows it, cancellation will happen at that point.

In someone can't tolerate that, then Promise.race is well-defined to do
exactly what you show, and works in harmony with this pattern. Why
reinvent the wheel?

And you'd Promise.race against the entire chain, so no need to nest this
pattern typically. This is what I mean with focusing on the minimal
use-case. Most people just want us to solve fetch already, so that
expensive network resources can be freed. To get out of the current
inertia, why not define:

fetch (url, { cancelPromise: token })


OTOH, why not to just use Promise.race directly and promote the pattern 
of "specify alternate result".

  1. This is more general;
  2. This allows creating decorators and use them like
shortcutAfter(5000, Promise.reject())(fetch(url))


now and use this pattern, and leave the more desirable { cancel } name
for whatever future invention we hope will replace it (or annex it if
nothing better materializes)?

.: Jan-Ivar :.


Herby

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


Shortcut for call of a method

2016-10-26 Thread Herby Vojčík

Hi!

Inspired by what I just did in Amber Smalltalk workspace:

  Smalltalk packages do: #commit

Eg., selector symbol #commit acting as an [ :x | x commit ] block, would 
it be feasible (it only saves 6 chars of nicely formatted "x => x", so 
maybe no) to have a similar shortcut in ES, as in:


  employees.map(.fullName)
  items.forEach(.init())
  products.filter(.includes(searchString))

Including things like `const emitFoo = .emit("foo");`.

Just a thought,

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


Re: "Super" hoisting

2016-05-13 Thread Herby Vojčík



Nicolas B. Pierron wrote:

I do not understand how having local variable should change any GC
pattern unless you are creating them in the for-loop body.


If I understand correctly, the problem is in not reusing the objects. If 
you do `var x = new X()` in every call of the method, GC should take 
care of every `new X()`. OTOH, they are young object, and young space 
should be this sort-of pool like quick thing.


But if creating them / deleting them is actually taking it's toll, 
having reused one object in this.x can save GC.


That's why I suggested that what is in way wanted here, is in fact 
pooling of X instances (and maybe not necessarily by instance of their 
client). Which can be inlined as well, as it is pretty easy:


  var x = poolOfXs.pop() || new X();

to get an x, and

  poolOfXs.push(x);

to put it back. This may actually save even more GC (as only as much 
instances are created as needed).


But again, I would still like to believe that garbage coilector is best 
pooler (though it needs to reinitialize the object each time, but OP 
told he was getting gc pauses).



Even though, Scalar Replacement optimizations (which are implemented
in all engine?) should be able to remove these allocations once the
optimizing JIT is reached, unless the "setFromPoint", "rotate", and
"average" functions are not inlined.


On Fri, May 13, 2016 at 3:09 PM, Herby Vojčík<he...@mailbox.sk>  wrote:


Brian Barnes wrote:

It could be, but there is a difference between:

var x;

and:

this.x


You should probably do `var x = XPool.get();` and at the end `XPool.put(x);`
and do `XPool`s for every possible X type which you want to not GC. And then
happily use local variable, as it should be. If things are not very parallel
/ reentrant, the pools will likely only contains zero / single element.



Because you’ll get leakage from the last run, so it would probably be
something that would need to be hinted, unless the engine was smart enough
to reset everything it hoisted (which is doable) but not optimal, as you
might always know that will be discarded (a really smart engine could
probably figure this out.)

Again, all this is to try to eliminate GC as much as possible.  It’s not a
philosophical argument, GC has pros and cons, it’s just bad for performance
sensitive stuff like games.  I do this all by hand now, so a super hoist
would just eliminate a lot of hard to read code I’ve written!

[>] Brian


On May 13, 2016, at 10:43 AM, Alan Johnson<a...@breakrs.com>   wrote:

Sounds like a potential JS engine optimization, rather than a language
feature per se.



On May 12, 2016, at 1:53 PM, Brian Barnes<gga...@charter.net>   wrote:

Not by my testing, at least.

My original example is a simple one to explain what the procedure is.
Here’s a more complex example, from my code, from my mesh classes.  This
function updates the vertices in the mesh based on the position of the bones
of a skeleton, it gets called every frame for every model mesh that can be
seen in the scene:

updateVertexesToPoseAndPosition(view,skeleton,angle,position)
{
var n,v;
var bone,parentBone;

// move all the vertexes

var vIdx=0;
var nIdx=0;

for (n=0;n!==this.vertexCount;n++) {
v=this.vertexList[n];

// bone movement

bone=skeleton.bones[v.boneIdx];

this.rotVector.setFromPoint(v.vectorFromBone);
this.rotVector.rotate(bone.curPoseAngle);

this.rotVector.x=bone.curPosePosition.x+this.rotVector.x;
this.rotVector.y=bone.curPosePosition.y+this.rotVector.y;
this.rotVector.z=bone.curPosePosition.z+this.rotVector.z;

this.rotNormal.setFromPoint(v.normal);
this.rotNormal.rotate(bone.curPoseAngle);

// average in any parent movement

if (v.parentBoneIdx!==-1) {
parentBone=skeleton.bones[v.parentBoneIdx];


this.parentRotVector.setFromPoint(v.vectorFromParentBone);
this.parentRotVector.rotate(parentBone.curPoseAngle);


this.parentRotVector.x=parentBone.curPosePosition.x+this.parentRotVector.x;

this.parentRotVector.y=parentBone.curPosePosition.y+this.parentRotVector.y;

this.parentRotVector.z=parentBone.curPosePosition.z+this.parentRotVector.z;

this.parentRotNormal.setFromPoint(v.normal);
this.parentRotNormal.rotate(parentBone.curPoseAngle);

this.rotVector.average(this.parentRotVector);
this.rotNormal.average(this.parentRotNormal);
}

// whole model movement

this.rotVector.rotate(angle);

this.drawVertices[vIdx++]=this.rotVector.x+position.x;
this.drawVertices[vIdx++]=this.rotVector.y+position.y;
this.drawVertices[vIdx++]=this.rotVector.z+position.z;

this.rotNormal.rotate(angle);

  

Re: "Super" hoisting

2016-05-13 Thread Herby Vojčík



Brian Barnes wrote:

It could be, but there is a difference between:

var x;

and:

this.x


You should probably do `var x = XPool.get();` and at the end 
`XPool.put(x);` and do `XPool`s for every possible X type which you want 
to not GC. And then happily use local variable, as it should be. If 
things are not very parallel / reentrant, the pools will likely only 
contains zero / single element.




Because you’ll get leakage from the last run, so it would probably be something 
that would need to be hinted, unless the engine was smart enough to reset 
everything it hoisted (which is doable) but not optimal, as you might always 
know that will be discarded (a really smart engine could probably figure this 
out.)

Again, all this is to try to eliminate GC as much as possible.  It’s not a 
philosophical argument, GC has pros and cons, it’s just bad for performance 
sensitive stuff like games.  I do this all by hand now, so a super hoist would 
just eliminate a lot of hard to read code I’ve written!

[>] Brian


On May 13, 2016, at 10:43 AM, Alan Johnson  wrote:

Sounds like a potential JS engine optimization, rather than a language feature 
per se.



On May 12, 2016, at 1:53 PM, Brian Barnes  wrote:

Not by my testing, at least.

My original example is a simple one to explain what the procedure is.  Here’s a 
more complex example, from my code, from my mesh classes.  This function 
updates the vertices in the mesh based on the position of the bones of a 
skeleton, it gets called every frame for every model mesh that can be seen in 
the scene:

   updateVertexesToPoseAndPosition(view,skeleton,angle,position)
   {
   var n,v;
   var bone,parentBone;

   // move all the vertexes

   var vIdx=0;
   var nIdx=0;

   for (n=0;n!==this.vertexCount;n++) {
   v=this.vertexList[n];

   // bone movement

   bone=skeleton.bones[v.boneIdx];

   this.rotVector.setFromPoint(v.vectorFromBone);
   this.rotVector.rotate(bone.curPoseAngle);

   this.rotVector.x=bone.curPosePosition.x+this.rotVector.x;
   this.rotVector.y=bone.curPosePosition.y+this.rotVector.y;
   this.rotVector.z=bone.curPosePosition.z+this.rotVector.z;

   this.rotNormal.setFromPoint(v.normal);
   this.rotNormal.rotate(bone.curPoseAngle);

   // average in any parent movement

   if (v.parentBoneIdx!==-1) {
   parentBone=skeleton.bones[v.parentBoneIdx];

   this.parentRotVector.setFromPoint(v.vectorFromParentBone);
   this.parentRotVector.rotate(parentBone.curPoseAngle);

   
this.parentRotVector.x=parentBone.curPosePosition.x+this.parentRotVector.x;
   
this.parentRotVector.y=parentBone.curPosePosition.y+this.parentRotVector.y;
   
this.parentRotVector.z=parentBone.curPosePosition.z+this.parentRotVector.z;

   this.parentRotNormal.setFromPoint(v.normal);
   this.parentRotNormal.rotate(parentBone.curPoseAngle);

   this.rotVector.average(this.parentRotVector);
   this.rotNormal.average(this.parentRotNormal);
   }

   // whole model movement

   this.rotVector.rotate(angle);

   this.drawVertices[vIdx++]=this.rotVector.x+position.x;
   this.drawVertices[vIdx++]=this.rotVector.y+position.y;
   this.drawVertices[vIdx++]=this.rotVector.z+position.z;

   this.rotNormal.rotate(angle);

   this.drawNormals[nIdx++]=this.rotNormal.x;
   this.drawNormals[nIdx++]=this.rotNormal.y;
   this.drawNormals[nIdx++]=this.rotNormal.z;
   }

   // set the buffers

   var gl=view.gl;
   gl.bindBuffer(gl.ARRAY_BUFFER,this.vertexPosBuffer);
   gl.bufferData(gl.ARRAY_BUFFER,this.drawVertices,gl.DYNAMIC_DRAW);

   gl.bindBuffer(gl.ARRAY_BUFFER,this.vertexNormalBuffer);
   gl.bufferData(gl.ARRAY_BUFFER,this.drawNormals,gl.STATIC_DRAW);
   }

Notice that rotVector, rotNormal, parentRotVector, and parentRotNormal, are all 
“this”, i.e., globals.  They are *only* used in this function, no where else in 
the class.  If I put them as local variables, I get enormous GC pauses.  If I 
don’t, I get none (granted, I have to do this everywhere, so it’s just not this 
function.)

The example I gave existed only to show how it would work; not a real example.  
Here’s a real example, that shows obvious problems with local variables.  Yes, 
these are objects.

Not that moving the objects would ONLY be something that happened at compile 
time and would be a hint; they wouldn’t be effected in the warm up runs.  You’d 
almost have to say that same hint would force a compile (which has it’s own 
problems.)

[>] Brian


On May 12, 2016, at 1:33 PM, Allen Wirfs-Brock  wrote:



On May 12, 2016, at 9:39 AM, Brian Barnes  wrote:

...
If I call doSomething a lot 

Re: [ small request - Javascript for javaing]

2016-01-01 Thread Herby Vojčík
Maybe we should rename the colloquial name of the language, to give 
clear signal to this kind of Javaist that Java should not have been 
there at first place and JS is something else. To retain .js extension 
it should be some J-word, like JumboScript, JiffyScript, JiveScript or 
something like that.


Bradley Meck wrote:

Actually if you look up the history of JS it is only called "Java"Script
because Java was popular, it originally was called LiveScript but due to
political pressures it was named JavaScript.

The underpinning semantics of the language are vastly different, with
the ideas of first class functions, and mutable runtime designed classes
(via prototypes).

Those in minds, please read the history of EcmaScript,
https://www.youtube.com/watch?v=fg4e-2lBw5E has some details, but there
is much more around the internet.

I suggest the following:

1. Can you point to backwards compatibility breakages?

We wish to avoid that.

2. Can you point to which features you want in the language?

Once again, the underlying semantics of
http://www.ecma-international.org/publications/standards/Ecma-262.htm
(see section #4) differ vastly (and never refers to being a subset or
compatible with) Java.


___
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 literal

2015-10-28 Thread Herby Vojčík



Alexander Jones wrote:

Ok, thanks for clarifying. Not only does it preserve order but it also
permits non-string keys. You're still missing one detail which is that
`bar` would actually be a variable not a string key.

Another example to clarify that the key part would be an expression:

```
Map#{foo(42) + 7: "bar"}
```

I prefer this over the precedent set by object literals which would
require that [] are used around a key expression ("computed key") simply


I, on the other hand, think it should match object literals completely. 
So your example would be


```
Map#{[foo(42)+7]: "bar"}
```

Yes, it's just for consistency and less WTF moment while learning the 
details.


OTOH, there could be consistent contraproposal of:

```
Object#{foo(42) + 7: "bar"}
null#{foo(42) + 7: "bar"}
#{foo(42) + 7: "bar"}
```

where the first is equivalent to {[foo(42)+7]: "bar"}, the second is 
pure container (Object.create(null)) filled with properties, and the 
third is the default case, but I don't know which of the previous two - 
the first is probably less confusing, though the feels more clean.



due to relieving the syntax noise, which is what this idea is all about.
Also, this is how it works in Python and I make no apologies about the
similarities ;)

Alex

On Wednesday, 28 October 2015, Viktor Kronvall
> wrote:

Hello Alexander,

I see now that I misread your desugaring.

I read:

```
Map#{1: 6, bar: 'Hello', 2: 8};
```
as being desugared to:

```
Map[Symbol.literalOf]({1: 6, bar: 'Hello', 2: 8}[Symbol.iterator]());
```

But your proposal clearly states that is should be:

```
Map[Symbol.literalOf]([[1, 6], ['bar', 'Hello'],
[2,8]][Symbol.iterator]());
```

Which would preserve lexical ordering of entries. The fault is
completely mine. Sorry.

I like this proposal as it is extensible and not that noisy in
syntax. Using the `#` for this doesn't
seem like a bad idea either. People coming from Erlang will be
familiar with this as well.


2015-10-28 10:53 GMT+01:00 Alexander Jones >:

Hi Victor

Not sure I understand - the desugaring I wrote would absolutely
preserve the written ordering because it speaks in terms of an
ArrayIterator of key-value pairs. If the map type to which it's
applied chooses to forget the ordering then that's fine.

Alex


On Wednesday, 28 October 2015, Viktor Kronvall
> wrote:

 > ```
>  const map = IMap#{"foo": 42, bar: 44};
>  ```
 > It could desugar as, for the sake of example:
 >
 > ```
 > Foo#{key: value, ...}
 > ➔
 > Foo[Symbol.literalOf]([[key, value], ...][Symbol.iterator]())
 > ```

I like this proposal. However, Maps should guarantee
insertion order when traversing the keys and values and
desugaring it like that does not respect this guarantee or
more precisely it will lead to (in my opinion) unexpected
order of the keys.

```
Object.keys({1: 6, bar: 'Hello', 2: 8}); // → [ '1', '2',
'bar' ]
```

If I'm not mistaken this will be same order for `{1: 6, bar:
'Hello', 2: 8}[Symbol.iterator]()`.

This implies that:

```
Map#{1: 6, bar: 'Hello', 2: 8};
```

Will not have entries in the order `[[1, 6], ['bar',
'Hello'], [2,8]]` but instead `[[1,6], [2,8], ['bar','Hello']]`.

This means that possible future destructuring of a Map will
be harder to reason about.


2015-10-28 2:21 GMT+01:00 Alexander Jones :

True, but easy to mess up and only be treated to a
runtime error. Three nested brackets at the start and
end could definitely be better, and this just encourages
people to use POJSOs instead. Also not a very uniform
interface if you look at how to construct a Map, Set or
Immutable.List at present, though admittedly constructor
call for the ES6 types would be a partial improvement.

On Wednesday, 28 October 2015, Tab Atkins Jr.
 wrote:

On Wed, Oct 28, 2015 at 8:36 AM, Alexander Jones
 wrote:
 > I agree this is pretty important. Using actual
maps really frees up a lot of
 > complexity, but the syntax is cumbersome to say
the least.
 >
 

Re: Map literal

2015-10-28 Thread Herby Vojčík



Herby Vojčík wrote:

OTOH, there could be consistent contraproposal of:

```
Object#{foo(42) + 7: "bar"}
null#{foo(42) + 7: "bar"}
#{foo(42) + 7: "bar"}
```

where the first is equivalent to {[foo(42)+7]: "bar"}, the second is
pure container (Object.create(null)) filled with properties, and the
third is the default case, but I don't know which of the previous two -
the first is probably less confusing, though the feels more clean.

... though the second feels more ...
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Destructuring: Add early errors for empty patterns?

2015-10-21 Thread Herby Vojčík
IMO this is ok, if the pattern is empty, nothing is extracted and 
assigned. I see it similar to using = in expressions: it is probably an 
error, jshint/IDEs should issue a warning, but I would not make an 
_error_ out of it (think for example cross-compilers who can produce 
dynamic destucturing assignments and they would need to parse it for 
"emptiness"); not consistent if special cases are errors.


Herby

Standards Zakas wrote:

Hi all,

In playing with destructuring, it seems like there are some syntax
gotchas that really should trigger some sort of error and instead fail
silently. For instance:

```
let {} = foo;
```

This line does absolutely nothing and is most likely an error on the
developer's part. However, this is completely valid syntax and not a
parsing error. Fortunately, it's pretty clear from looking at it that
there's a problem. Another example isn't so clear:

```
let { bar: {} } = foo;
```

This one, I'd argue, is even worse. It looks like it should do
something, but silently does nothing.

Is there any possibility to add an early error for empty destructuring
patterns (array and object)? It seems like this would save developers a
lot of trouble in the long run.


--

Nicholas C. Zakas
http://www.nczonline.net
@slicknet

___
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: Weak References

2015-09-27 Thread Herby Vojčík
A naive question: don't you get working weakref by using a WeakMap and 
getting and setting using the same key? A naive point of view suggests 
that. What am I not seeing here?


Herby

Isiah Meadows wrote:

I'm resurrecting this [1] because I have found a use case where I needed
a weak reference. Is there any chance this could get into the language?

Here's my particular use case: making a stream with a rotating
destination that itself acts as a stream (snippet of that code, or what
I'd like it to be).

```js
function rotateStream(interval, format) {
 // Without the weak reference here, there's a memory leak
 const ref = new WeakReference({})
 setStream(ref.get(), format)
 setInterval(function () {
 if (ref.exists()) setStream(ref.get(), format)
 else clearInterval(this)
 }, interval)
 return ref.get()
}
```

This basically rotates an active stream, with the weak reference
pointing to the said stream. The alternative requires explicit marking
(in this case, with a `close` method):

```js
function leakyRotateStream(interval, format) {
 let stream = {close() {
 clearInterval(timer)
 timer = stream = null
 }}
 const timer = setInterval(function () {
 setStream(stream, format)
 }, interval)
 setStream(stream, format)
 return stream
}
```

In this use case, weak references would simplify the implementation and
reduce memory costs. And I would rather take advantage of the GC
machinery than explicit memory management (as explicit as C), as it
would be easier to collect when that's the only thing referenced.

(The setInterval callback is gc'd with all its references when it's
cleared from within.)

Thankfully, I'm using Node.js, so `weak` [2] is an option (the only
option, really). But I would definitely appreciate if it was available
in JS proper, across engines. V8, SpiderMonkey, and JSC all have weak
references to JS objects as part of their public API, and I would be
surprised if the implementation work would be anything significant.

[1]: https://esdiscuss.org/topic/what-is-the-status-of-weak-references
[2]: https://github.com/TooTallNate/node-weak

--
Isiah Meadows

___
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: Exponentiation operator precedence

2015-09-25 Thread Herby Vojčík



Claude Pache wrote:


I just wonder why it is important that unary binds tighter? For
instance, before I carefully studied the issue of this thread, I have
never expected that unary minus binds tighter than binary multiplication
operator in expressions like `-2*x` (although it does not matter in that
case).

Making the parentheses mandatory here will be somewhat annoying in
perfectly reasonable expressions, where you usually don’t use
parentheses in real math notation., like:
```
let s2 = - x**2 - y**2 - z**2 + t**2
```


I would overcome it and do not write the parens:

  let s2 = 0 - x**2 - y**2 - z**2 + t**2

Writing mandatory parens here is ugly.

In fact, I am surprised "-2" is unary minus with 2, I thought it is 
number -2. And similarly to Claude, I always read -x*y in math notation, 
that is, as -(x*y). Luckily, for multiplication it does not matter.


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


Re: Exponentiation operator precedence

2015-09-25 Thread Herby Vojčík



Herby Vojčík wrote:



Claude Pache wrote:


I just wonder why it is important that unary binds tighter? For
instance, before I carefully studied the issue of this thread, I have
never expected that unary minus binds tighter than binary multiplication
operator in expressions like `-2*x` (although it does not matter in that
case).

Making the parentheses mandatory here will be somewhat annoying in
perfectly reasonable expressions, where you usually don’t use
parentheses in real math notation., like:
```
let s2 = - x**2 - y**2 - z**2 + t**2
```


I would overcome it and do not write the parens:

let s2 = 0 - x**2 - y**2 - z**2 + t**2


An off-topic thought: Unary minus (and plus) are only used with numbers 
in JS. Why are they treated specially, not as hidden 0+x and 0-x, 
respectively? That would be logical (unary plus and minus would have 
same precendence as binary plus and minus).



Writing mandatory parens here is ugly.

In fact, I am surprised "-2" is unary minus with 2, I thought it is
number -2. And similarly to Claude, I always read -x*y in math notation,
that is, as -(x*y). Luckily, for multiplication it does not matter.

Herby
___
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: Template strings as a template language.

2015-09-15 Thread Herby Vojčík
OTOH, it is a question if it is wprth it at all, as we have IIFEs and maybe 
will have do expressions, so you can stick anything to template string anyway. 
OTYOH, new Regexp had its merits

Dňa 15. septembra 2015 7:24:26 CEST používateľ Thomas 
 napísal:
> With all due respect to your solution (it works, and it works well),
> it's far from ideal to be relying upon `with` and Function. I guess
> what I'm trying to get at is - wouldn't it be better to think about
> having a built in version that didn't use with or eval (should be easy
> enough)? I sense that you're not confident about it being successful
> in that sense, but a built in function for this trumps with and
> Function any day of the week.
> 
> Thomas 
> 
> > On 15 Sep 2015, at 3:42 AM, Andrea Giammarchi
>  wrote:
> > 
> > nobody here raised the minimal interest in what I've achieved with
> those few lines of code, I rather had people saying "with statement?
> ewww" or similar reactions about Function like yours ... I don't think
> as proposal would ever make it, it's too easy to polyfill so I'd
> expect many - 1
> > 
> > ¯\_(ツ)_/¯
> > 
> >> On Mon, Sep 14, 2015 at 5:23 PM, Thomas
>  wrote:
> >> Sorry, I sent that before I saw your other explanation. 
> >> 
> >> On a second look that function does work pretty well. The use of
> Function still means strings are being evaluated at runtime, but I
> agree that it's safer/better than eval (though I'm not sure why CSP
> would still like it over eval).
> >> 
> >> Have you any plans to make the String.prototype.template function a
> proposal?
> >> 
> >> Thomas
> >> 
> >>> On 15 Sep 2015, at 1:52 AM, Andrea Giammarchi
>  wrote:
> >>> 
> >>> again, Function **is** better and different than eval, but I see
> this conversation is bringing nothing so I'll just stop explaining.
> >>> 
> >>> Regards
> >>> 
>  On Mon, Sep 14, 2015 at 3:47 PM, Thomas
>  wrote:
>  Doesn't the code in that gist create functions at runtime from
> strings? If so that's not any better than eval. 
>  
> > On 14 Sep 2015, at 8:50 PM, Andrea Giammarchi
>  wrote:
> > 
> > sorry, early send (I think it was a ctrl+return ? ) ... I was
> saying ..
> > 
> > without using eval and already discussed months ago:
> > https://gist.github.com/WebReflection/8f227532143e63649804
> > 
> > it's based on the glorious `with` statement and it works like a
> charm
> > 
> > Regards
> > 
> > 
> > 
> > 
> > 
> > 
> >> On Mon, Sep 14, 2015 at 11:49 AM, Andrea Giammarchi
>  wrote:
> >> without using eval, discussed already months ago
> >> 
> >> 
> >>> On Mon, Sep 14, 2015 at 6:03 AM, Thomas
>  wrote:
> >>> For those interested, this gist better shows what's being
> discussed: https://gist.github.com/thomasfoster96/193e7c08aae499f810a1
> >>> 
> >>> Ron: Yes, that's already possible - but tagged template
> strings don't really offer much of an advantage over a function as far
> as templating goes (IMHO).
> >>> 
> >>> Thomas
> >>> 
> >>> On 14 Sep 2015, at 11:04 AM, Ron Buckton
>  wrote:
> >>> 
>  This is theoretically possible:
>  
>  ```
>  let t = $template`
>    ${$item.permalink}
>    ${$each($item.comments)`
>  ${$parent.permalink}
>  ${$if($item.title)`
>    ${$parent.permalink}
>  `}
>    `}
>  `;
>  let s = t(data);
>  ```
>  
>  ...given an adequate implementation using proxies (to create
> bindings for e.g. `$item.permalink` for later evaluation) and tagged
> template functions. Whether or not this would make for a reasonable
> implementation is left to the reader.
>  
>  Ron
>  From: Isiah Meadows
>  Sent: ‎9/‎13/‎2015 4:15 PM
>  To: Mark S. Miller
>  Cc: Bob Myers; es-discuss
>  Subject: Re: Template strings as a template language.
>  
>  On Sun, Sep 13, 2015 at 7:09 PM, Mark S. Miller
>  wrote:
>  >
>  >
>  > On Sun, Sep 13, 2015 at 8:58 AM, Bob Myers 
> wrote:
>  >>
>  >> Templating languages typically "compile" templates into
> functions through
>  >> various lexical transformations.
>  >>
>  >> Consider a template file foo.tem:
>  >>
>  >> ```
>  >> My name is
> ${https://na01.safelinks.protection.outlook.com/?url=this.name=01%7c01%7cron.buckton%40microsoft.com%7ce705066eae3849ee21f008d2bc913033%7c72f988bf86f141af91ab2d7cd011db47%7c1=CY6YpX1n5jLScYGX2W1tIi2ndGlA7WI8ZTJUZjDL2Gw%3d}.
>  >> ```
>  >>
>  

Re: Template strings as a template language.

2015-09-15 Thread Herby Vojčík
 

Dňa 15. septembra 2015 12:05:16 CEST používateľ "Herby Vojčík" 
<he...@mailbox.sk> napísal:
> OTOH, it is a question if it is wprth it at all, as we have IIFEs and
> maybe will have do expressions, so you can stick anything to template
> string anyway. OTYOH, new Regexp had its merits

s/had/has/

> Dňa 15. septembra 2015 7:24:26 CEST používateľ Thomas
> <thomasjamesfos...@bigpond.com> napísal:
> > With all due respect to your solution (it works, and it works well),
> > it's far from ideal to be relying upon `with` and Function. I guess
> > what I'm trying to get at is - wouldn't it be better to think about
> > having a built in version that didn't use with or eval (should be
> easy
> > enough)? I sense that you're not confident about it being successful
> > in that sense, but a built in function for this trumps with and
> > Function any day of the week.
> > 
> > Thomas 
> > 
> > > On 15 Sep 2015, at 3:42 AM, Andrea Giammarchi
> > <andrea.giammar...@gmail.com> wrote:
> > > 
> > > nobody here raised the minimal interest in what I've achieved with
> > those few lines of code, I rather had people saying "with statement?
> > ewww" or similar reactions about Function like yours ... I don't
> think
> > as proposal would ever make it, it's too easy to polyfill so I'd
> > expect many - 1
> > > 
> > > ¯\_(ツ)_/¯
> > > 
> > >> On Mon, Sep 14, 2015 at 5:23 PM, Thomas
> > <thomasjamesfos...@bigpond.com> wrote:
> > >> Sorry, I sent that before I saw your other explanation. 
> > >> 
> > >> On a second look that function does work pretty well. The use of
> > Function still means strings are being evaluated at runtime, but I
> > agree that it's safer/better than eval (though I'm not sure why CSP
> > would still like it over eval).
> > >> 
> > >> Have you any plans to make the String.prototype.template function
> a
> > proposal?
> > >> 
> > >> Thomas
> > >> 
> > >>> On 15 Sep 2015, at 1:52 AM, Andrea Giammarchi
> > <andrea.giammar...@gmail.com> wrote:
> > >>> 
> > >>> again, Function **is** better and different than eval, but I see
> > this conversation is bringing nothing so I'll just stop explaining.
> > >>> 
> > >>> Regards
> > >>> 
> > >>>> On Mon, Sep 14, 2015 at 3:47 PM, Thomas
> > <thomasjamesfos...@bigpond.com> wrote:
> > >>>> Doesn't the code in that gist create functions at runtime from
> > strings? If so that's not any better than eval. 
> > >>>> 
> > >>>>> On 14 Sep 2015, at 8:50 PM, Andrea Giammarchi
> > <andrea.giammar...@gmail.com> wrote:
> > >>>>> 
> > >>>>> sorry, early send (I think it was a ctrl+return ? ) ... I was
> > saying ..
> > >>>>> 
> > >>>>> without using eval and already discussed months ago:
> > >>>>> https://gist.github.com/WebReflection/8f227532143e63649804
> > >>>>> 
> > >>>>> it's based on the glorious `with` statement and it works like
> a
> > charm
> > >>>>> 
> > >>>>> Regards
> > >>>>> 
> > >>>>> 
> > >>>>> 
> > >>>>> 
> > >>>>> 
> > >>>>> 
> > >>>>>> On Mon, Sep 14, 2015 at 11:49 AM, Andrea Giammarchi
> > <andrea.giammar...@gmail.com> wrote:
> > >>>>>> without using eval, discussed already months ago
> > >>>>>> 
> > >>>>>> 
> > >>>>>>> On Mon, Sep 14, 2015 at 6:03 AM, Thomas
> > <thomasjamesfos...@bigpond.com> wrote:
> > >>>>>>> For those interested, this gist better shows what's being
> > discussed:
> https://gist.github.com/thomasfoster96/193e7c08aae499f810a1
> > >>>>>>> 
> > >>>>>>> Ron: Yes, that's already possible - but tagged template
> > strings don't really offer much of an advantage over a function as
> far
> > as templating goes (IMHO).
> > >>>>>>> 
> > >>>>>>> Thomas
> > >>>>>>> 
> > >>>>>>> On 14 Sep 2015, at 11:04 AM, Ron Buckton
> > <ron.buck...@microsoft.com> wrote:
> > >>>>>>> 
>

Re: Template strings as a template language.

2015-09-15 Thread Herby Vojčík



Andrea Giammarchi wrote:

Yet it doesn't play well with i18n since arguments passed to the IIFE
would still come from the current local scope. RegExp would play nicer


Oh, I meant it other way, my dense communication again produce a 
misunderstanding, I meant something like "well, one can make regexp as 
well using eval('/'+aString.replace(/\//g, '\\/')+'/') or so, but there 
still is new Regexp there. So, having string-to-regexp in language, 
maybe we can as well have string-to-template.



but it can't do fancy inline JS evaluation, example:

```js
String.prototype.template = function (o) {
   return this.replace(/\$\{(.+?)\}/g, function ($0,  $1) {
 return  o[$1];
   });
};

'Helo ${name}!'.template({name: 'World'});
```

That could also work combined with template strings so that HTML could
be written like

```js
`click`.template({query:
encodeURIComponent('hope')});
```

But it's not so cool and footgun prone to remember the `\${...}` escape.
Oh well, not sure how this thread will end up. Maybe there's nothing to
do, let's stick with tooling and libraries :-)

Regards


On Tue, Sep 15, 2015 at 11:05 AM, Herby Vojčík <he...@mailbox.sk
<mailto:he...@mailbox.sk>> wrote:

OTOH, it is a question if it is wprth it at all, as we have IIFEs
and maybe will have do expressions, so you can stick anything to
template string anyway. OTYOH, new Regexp had its merits

Dňa 15. septembra 2015 7:24:26 CEST používateľ Thomas
<thomasjamesfos...@bigpond.com
<mailto:thomasjamesfos...@bigpond.com>> napísal:

With all due respect to your solution (it works, and it works
well), it's far from ideal to be relying upon `with` and
Function. I guess what I'm trying to get at is - wouldn't it be
better to think about having a built in version that didn't use
with or eval (should be easy enough)? I sense that you're not
confident about it being successful in that sense, but a built
in function for this trumps with and Function any day of the week.

Thomas

On 15 Sep 2015, at 3:42 AM, Andrea Giammarchi
<andrea.giammar...@gmail.com
<mailto:andrea.giammar...@gmail.com>> wrote:


nobody here raised the minimal interest in what I've achieved
with those few lines of code, I rather had people saying "with
statement? ewww" or similar reactions about Function like
yours ... I don't think as proposal would ever make it, it's
too easy to polyfill so I'd expect many - 1

¯\_(ツ)_/¯

On Mon, Sep 14, 2015 at 5:23 PM, Thomas
<thomasjamesfos...@bigpond.com
<mailto:thomasjamesfos...@bigpond.com>> wrote:

Sorry, I sent that before I saw your other explanation.

On a second look that function does work pretty well. The
use of Function still means strings are being evaluated at
runtime, but I agree that it's safer/better than eval
(though I'm not sure why CSP would still like it over eval).

Have you any plans to make the String.prototype.template
function a proposal?

Thomas

On 15 Sep 2015, at 1:52 AM, Andrea Giammarchi
<andrea.giammar...@gmail.com
<mailto:andrea.giammar...@gmail.com>> wrote:


again, Function **is** better and different than eval,
but I see this conversation is bringing nothing so I'll
just stop explaining.

Regards

On Mon, Sep 14, 2015 at 3:47 PM, Thomas
<thomasjamesfos...@bigpond.com
<mailto:thomasjamesfos...@bigpond.com>> wrote:

Doesn't the code in that gist create functions at
runtime from strings? If so that's not any better
than eval.

On 14 Sep 2015, at 8:50 PM, Andrea Giammarchi
<andrea.giammar...@gmail.com
<mailto:andrea.giammar...@gmail.com>> wrote:


sorry, early send (I think it was a ctrl+return ? )
... I was saying ..

without using eval and already discussed months ago:
https://gist.github.com/WebReflection/8f227532143e63649804

it's based on the glorious `with` statement and it
works like a charm

Regards






On Mon, Sep 14, 2015 at 11:49 AM, Andrea Giammarchi
<andrea.giammar...@gmail.com
<mailto:andrea.giammar...@gmail.com>> wrote:

without using eval, discussed already months ago


On Mon, Sep 14, 2015 at 6:03 AM, Thomas
<thomasjamesfos...@bigpond.com
<mailto:thomasjamesfos...@bigpond.com>> wrote:

For those interested, this gist b

Re: Template strings as a template language.

2015-09-14 Thread Herby Vojčík



Andrea Giammarchi wrote:

sorry, early send (I think it was a ctrl+return ? ) ... I was saying ..

without using eval and already discussed months ago:
https://gist.github.com/WebReflection/8f227532143e63649804


I had the impression the "no-eval" was in fact "no eval or Function", in 
which case this does not count either.




it's based on the glorious `with` statement and it works like a charm

Regards






On Mon, Sep 14, 2015 at 11:49 AM, Andrea Giammarchi
> wrote:

without using eval, discussed already months ago


On Mon, Sep 14, 2015 at 6:03 AM, Thomas
> wrote:

For those interested, this gist better shows what's being
discussed:
https://gist.github.com/thomasfoster96/193e7c08aae499f810a1

Ron: Yes, that's already possible - but tagged template strings
don't really offer much of an advantage over a function as far
as templating goes (IMHO).

Thomas

On 14 Sep 2015, at 11:04 AM, Ron Buckton
>
wrote:


This is theoretically possible:

```
let t = $template`
  ${$item.permalink}
  ${$each($item.comments)`
${$parent.permalink}
${$if($item.title)`
  ${$parent.permalink}
`}
  `}
`;
let s = t(data);
```

...given an adequate implementation using proxies (to create
bindings for e.g. `$item.permalink` for later evaluation) and
tagged template functions. Whether or not this would make for
a reasonable implementation is left to the reader.

Ron

From: Isiah Meadows 
Sent: ‎9/‎13/‎2015 4:15 PM
To: Mark S. Miller 
Cc: Bob Myers ; es-discuss

Subject: Re: Template strings as a template language.

On Sun, Sep 13, 2015 at 7:09 PM, Mark S. Miller
> wrote:
>
>
> On Sun, Sep 13, 2015 at 8:58 AM, Bob Myers > wrote:
>>
>> Templating languages typically "compile" templates into
functions through
>> various lexical transformations.
>>
>> Consider a template file foo.tem:
>>
>> ```
>> My name is

${https://na01.safelinks.protection.outlook.com/?url=this.name=01%7c01%7cron.buckton%40microsoft.com%7ce705066eae3849ee21f008d2bc913033%7c72f988bf86f141af91ab2d7cd011db47%7c1=CY6YpX1n5jLScYGX2W1tIi2ndGlA7WI8ZTJUZjDL2Gw%3d

}.
>> ```
>>
>> Lexically transform this into
>>
>> ```
>> function foo() {
>>   return `My name is ${this.name |}.`;
>> }
>>
>> Then invoke the template as eg
>>
>> ```
>> foo.call({name: 'Bob'})
>> ```
>>
>> Having said that, I doubt if ES6 template strings serve as a
useful basis
>> for a full-fledged templating system. To take just one basic
example, how
>> would one implement the equivalent of `{{#if}}`?
>
>
> What does `{{#if}}` mean?
>

An example from Handlebars' website (which is likely where he
drew the
syntax from):

```
{{permalink}}
{{#each comments}}
  {{../permalink}}

  {{#if title}}
{{../permalink}}
  {{/if}}
{{/each}}
```



>>
>>
>> Bob
>>
>>
>> ___
>> es-discuss mailing list
>> es-discuss@mozilla.org 
>>

https://na01.safelinks.protection.outlook.com/?url=https%3a%2f%2fmail.mozilla.org%2flistinfo%2fes-discuss=01%7c01%7cron.buckton%40microsoft.com%7ce705066eae3849ee21f008d2bc913033%7c72f988bf86f141af91ab2d7cd011db47%7c1=Vk9C%2fonHktgLCsW%2f395PrpBWefRcs6XFqJk7HTVbunE%3d


>>
>
>
>
> --
> Cheers,
   

Re: Computed Property Name Shorthand Proposal

2015-08-30 Thread Herby Vojčík



Alexander Jones wrote:

That's exactly what this is. I appreciate the beauty in symmetry, but I
think -1.


I second this.


On 27 August 2015 at 17:25, Kevin Smith zenpars...@gmail.com
mailto:zenpars...@gmail.com wrote:

I'd expect the following to work, given that the prop expression
evaluates to 'bar', and bar is in context.

var foo = 'bar'
var bar = 'ponyfoo'
var baz = { [foo] }
console.log(baz)
// - { bar: 'ponyfoo' }


Hmmm...  I'm not sure I would expect any such thing.  It seems like
you're proposing some kind of dynamic eval-ish variable binding
lookup, which is probably going to be a no-go.

Kevin


___
es-discuss mailing list
es-discuss@mozilla.org mailto: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


Reified lvalue (was: Re: Extensible destructuring proposal)

2015-08-19 Thread Herby Vojčík



Bergi wrote:

Samuel Hapák schrieb:


The main idea is, that if object defines `Symbol.get` method, it gets
used to access properties of object instead of `[]` when destructuring.


Aw, when I read extensible destructuring I had hoped to see an
extension to the destructuring syntax, not to see how semantics of
destructuring objects are changed.

What do you think about extractor functions, like in Scala
http://www.scala-lang.org/old/node/112?
Instead of `unapply` or `unapplySeq` methods we'd probably use an
`@@extractor` (`Symbol.extractor`) method or so, allowing us to do

let Map({a, b, c}) = myMap;

let List(a, b, c) = myList;

const Map({author: Map({name: {first, last}, birthdate})}) = book;

which would desugar to

let [{a, b, c}] = Map[Symbol.extractor](myMap);

let [a, b, c] = List[Symbol.extractor](myList);

const [{author: __author}] = Map[Symbol.extractor](book);
const [{name: {first, last}, birthdate}] = Map[Symbol.extractor](__author);

where each extractor method would return an Iterable that is assigned to
the arguments of the extractor. (A Proxy to lazily destructure object
literals in there is a good idea, thanks @Claude).

This would even allow us to call functions on destructuring, think about
module imports:

// a.js
export default function factory(options) {
…
return moduleInstance;
}

// b.js
const NoOptions = {
[Symbol.extractor](factory) { return [factory()]; }
};
const WithOptions = (...args) = ({
[Symbol.extractor](factory) { return [factory(...args)]; }
});

import NoOptions(A) from a;
import WithOptions(config)(A) from a;
// A === moduleInstance

What do you think about that?


Nice, but as Samuel mentioned, you need to actually transform the data 
so it can be fed to stock destructurer.


What I came up is the idea of reified lvalue, the object that 
describes the (complex, destucturing) lvalue used for assignment (for 
example as the list of simple expression assignments, internally); and 
that such object could be transformed.


Like (very rough examples; just an idea, not the spec):

  let a = 4;

  outer a - input


  let {a,c:{b}} = foo;

  outer a - input.a
  tmp0 - input.c
  outer b - tmp0.b


  let {a,c:Map({b})} = foo;

  Map[Symbol.lvalue] gets outer b - input.b and transforms it to 
outer b - input.get('b'), so the result would be:


  outer a - input.a
  tmp0 - input.c
  outer b - tmp0.get('b')


  let Map(a,c:Map({b})) = foo;

  Map[Symbol.lvalue] get the above descriptor and transforms it to

  outer a - input.get('a')
  tmp0 - input.get('c')
  outer b - tmp.get('b')

If things like Map[Symbol.lvalue] would be frozen (or just speculatively 
supposed not to be mutated), this can as well be done at compile time, 
so the resulting code could stay fast.



Bergi


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


Re: Proposal for a null coalescing operator

2015-08-17 Thread Herby Vojčík



Michael McGlothlin wrote:

Another place JS would create a consideration is NaN. You might want
that to play well with the operator. Possibly you could consider ?? for


You've got || for wider range of nullish values. Proposal (and, in my 
case, personally felt need) for ?? is to only cover null and undefined 
(== null) selection.



a wider range of nullish values and ??? for ONLY undefined.

x = parseInt (a) ?? 42
x = a.nada ??? 42





 Michael McGlothlin

On Aug 16, 2015, at 10:32 PM, Kevin Smith zenpars...@gmail.com
mailto:zenpars...@gmail.com wrote:


A link to a wikipedia article is not *actually* a proposal : )

As Michael points out, you need to at least provide some consideration
for null vs. undefined. I would also like to see some thought given to
how such an operator might interact with a null propagation operator,
discussed here:

https://esdiscuss.org/topic/existential-operator-null-propagation-operator

(Link appears to be temporarily not working...)

___
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: July 30 2015 Meeting Notes

2015-08-11 Thread Herby Vojčík



Rick Waldron wrote:

(Slides are at https://github.com/tc39/tc39-notes/tree/master/es7/2015-07 )


# July 30 2015 Meeting Notes

Allen Wirfs-Brock (AWB), Sebastian Markbage (SM), Jafar Husain (JH),
Eric Farriauolo (EF), Caridy Patino (CP), Waldemar Horwat (WH), Istvan
Sebastian (IS), Mark Miller (MM), Adam Klein (AK), Michael Ficarra (MF),
Peter Jensen (PJ), Domenic Denicola (DD), Jordan Harband (JHD), Jonathan
Turner (JT), Paul Leathers (PL), Chip Morningstar (CM), Vladimir Matveev
(VM), Ron Buckton (MS), Brian Terlson (BT), Alan Schmitt (AS), Ben
Newman (BN), Mohamed Hegazy (MH), Abhijith Chatra (AC), Tom Care (TC),
John Neumann  (JN), Dave Herman (DH), Brendan Eich (BE), Daniel
Ehrenberg (DE), Dan Gohman (DG), Andreas Rossberg (ARB), Rick Waldron
(RW), Mike Pennisi (MP), Akrosh Gandhi (AG), Jonathan Sampson (JS)


## 6.4 Advance Async Functions to Stage 2

(Brian Terlson)

[Slides](async-function-updates.pdf)

BT:
Updates from Last Time

- Complete spec available ( http://tc39.github.io/ecmascript-asyncawait/
/ https://github.com/tc39/ecmascript-asyncawait )
- Removed `await *`
- Implemented in Babel
- Losts of positive feedback from the web

DH: Future proof for potential future syntax extensions

DD: Clarify not `await *`

BT: `await *` was not useful. If there is a proposal for a useful
semantics, then good, but not in this proposal.

Questions

- Async Arrow Function
   - async (a, b) = await a + await b;
   - (a, b) @= await a + await b;


DE: What's the issue with the first?

BT: `async` not a keyword and that could be a call: `async(a, b)`

MM: @ seems like a poor choice, but I don't have an alternate suggestion


Just a feeling-based one, but contrary to the straight sync =, the 
async could be curly ~.


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


Re: please add orEqual operator

2015-08-10 Thread Herby Vojčík



myemailu...@gmail.com wrote:

I one day writing js thought why there is no operator for ||= there


The problem with || (and, consequently, ||=) is that it uses ToBoolean. 
We have all used to it, but I'd bet what we mostly want is if (x == 
null) ..., so I think ||= should NOT be added to the language and || 
used as value || anotherValue should be left to rot (as a boolean 
short-circuit in if/while it is, of course, indispensable); on the other 
hand, we should add something like value ?? anotherValue and lvalue ??= 
anotherValue, instead, which would only kick in case of null/undefined.



should be syntax makes sense, then i learned some ruby and it had this
already. Now i was convinced it makes sense afterall.

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


Re: [Meta] Proposal: Switch es-discuss from a mailing list to using the TC39 GitHub issue tracker for discussion.

2015-07-23 Thread Herby Vojčík



Brandon Andrews wrote:

I was looking at the most recent notes. https://esdiscuss.org/notes/2015-05-27 
One thing stuck out to me is that ECMA uses GitHub a lot. There was a line that 
caught my attention:



?: What needs to live on the ECMA GitHub?



Waldemar Horwat/Allen Wirfs-Brock: Any contributions need to be in some format 
that ECMA can archive, for legal, librarian, and historical needs — imagine 
someone needing to track down the history of some contributions 15 years from 
now. For individual documents (pdfs, etc.) the simplest way is to send them via 
the ECMA reflector. ECMA keeps an archive of those forever. For ongoing things 
use an ECMA-sanctioned repository such as ECMA's GitHub.


The line ECMA-sanctioned repository such as ECMA's GitHub makes it sound like 
GitHub is relatively trusted as an archival system.


Personal note: If you must kill es-discuss and move it, move it to 
medium that is not political, that is, not to github. Github has 
recently made a move that pushes me to leave it as soon as I find 
suitable alternative. It shouldn't be that everything is in github, 
because github will then have too much power, and it is unable to resist 
the urge to abuse it. In the similar vein, you cannot automatically 
assume everyone has / can create account on github. Some have reasons 
not to github.


But just recently there was a thread on moving it from ML format to 
forum format, and the result was, for the moment, not moving it.



I know many people here probably love mailing lists, but I've never much cared for them. 
They're often riddled with mistakes and formatting errors that can never really be fixed. 
People also reply wrong for instance fragmenting discussions. This can hurt discussion. 
Also some people have problems replying to them or simply don't feel comfortable using 
them. I've pointed people here to view and gotten replies like I don't have time to 
use a mailing list. The https://esdiscuss.org/ page I think helps, but it has its 
own issues. Most people don't know it uses the GitHub styling so it garbles a lot of 
things from its plaintext version. Also, as I figured out finally, only moderators can 
edit their own posts which means editing to try to clean things up is impossible.


So my proposal is for TC39 to create an esdiscuss project at 
https://github.com/tc39. So people would just go to 
https://github.com/tc39/esdiscuss. Then using their GitHub account they could 
easily login and post issues and comments without having to subscribe or figure 
out how to use mailing lists with their email client. GitHub's issue tracker 
offers many nice features also that mailing lists lack. You can have labels 
which is amazing for archiving. It's also very easy to search. Users can also 
edit their posts and past code examples trivially into their comments so 
comments and replies flow smoothly. As an example look at 
https://github.com/dotnet/roslyn/labels/Area-Language%20Design. That's a link 
to all the language design proposals and discussions for Roslyn.


Also from what I can tell there's no country that currently blocks GitHub. At 
one point Russia, China, and India blocked the site, but from what I'm reading 
they no longer block it. In the future that might not always be the case. 
That's the biggest downside I can think of that would be a potential issue.


I see using GitHub's issue tracker as a way of encouraging more discussion 
also. Pretty much every Javascript developer has a GitHub account for working 
with various Node.JS projects so they'd probably be more receptive following 
and joining in on the discussion. GitHub also has a very easy to use moderation 
system so it's easy to correct small formatting errors and titles to make 
searching simple and terminology consistent. It's also easy to see which topics 
are active and which are done being discussed.

Is there any support for something like this?


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


Re: ES8 Proposal: Optional Static Typing

2015-07-19 Thread Herby Vojčík



Filip Pizlo wrote:

Hi Brandon,

Thanks for writing this up!

My personal feeling is that I’d rather ES not have static typing of this
form. I believe it makes the language substantially more complex, and to
me it feels best to try to minimize the growth of the language in order
to ensure that those things that we do add are added in a compatible and
sound way. Also, I wonder if static typing wouldn’t work out better if
instead of extending ES, you found a way to instead make wasm
(https://www.w3.org/community/webassembly/) powerful enough to handle
the language that you want. The benefit of that route is that (1) there


+1


is already support behind wasm and what I see as a broad desire to
enable wasm to handle statically-typed object-oriented/functional
languages, and (2) it’s a clean slate, so a proposal doesn’t have to
worry about the compatibility issues.


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


Re: ES8 Proposal: Optional Static Typing

2015-07-19 Thread Herby Vojčík

Two things:

I heard Gilad Bracha in ECOOP to say [paraphrase] optional typing is 
great to help with documentation, and to help the tools; but it should 
not touch the runtime. This is what I take for my own as well, nicely 
said. Your overload proposition, though, changes the language so that 
this would need to touch the runtime. It seems there are two distinct 
view on bringing static typing in to dynamically-typed languages: one of 
them in line with the aformentioned, the other taking over the semantic 
and runtime as well. There are also two terms: optional typing and 
gradual typing. I really don't know if those are defined precisely, 
but there seemed to be a sentiment that optional typing is the 
Gilad-Brachaish Strongtalk-like view, and gradual typing is the view 
that actually changes the semantics of the language and the runtime. 
What I wanted to say, is, that maybe this thread should be called ES8 
Proposal: Gradual Static Typing.


And I forgot the second one. Though I personally think changing the 
semantics (do gradual typing) would change the language to something 
very different and may complicate the good old duck-typing way of doing 
things. Truly optional typing, in the sense of help the tools and 
document is good, though. But it is completely different debate (some 
foods for though: 1. We have JSDoc which already does that - we can 
type-annotate and tools do the work; 2. An eye-opener is to learn that 
there is distinction between nominal types and structural types. Does it 
not suit ES, as a duck-typing language, to have optional structural 
typing instead of optional nominal typing?).


Herby


Brandon Andrews wrote:

ES8 Proposal: Optional Static Typing

It was once said by Brendan Eich that 'Types are hard. This doesn't mean no, 
never.' It's been a while since ES4. With ES6's TypedArrays and classes finalized 
and ES7 SIMD getting experimental tests, ECMAScript is in a good place to finally discuss 
types again. The demand for types as a different approach to code has been so strong in 
the past few years that separate languages have been created to deal with the perceived 
shortcomings. Types won't be an easy discussion, nor an easy addition, since they touch a 
large amount of the language; however, they are something that needs rigorous discussion. 
I'm hoping this initial proposal can be a way of pushing the ball forward. Turning this 
into an official proposal discussed by TC39 is the goal. This could very well be most of 
ES8 due to the complexity.

Since it would be potentially years before this would be implemented this proposal 
includes a new keyword enum for enumerated types and the following types:

number
bool
string
object
int8/16/32/64
uint8/16/32/64
bignum
float16/32/64/80/128
decimal32/64/128
int8x16/16x8/32x4/64x2/8x32/16x16/32x8/64x4
uint8x16/16x8/32x4/64x2/8x32/16x16/32x8/64x4
float32x4/64x2/32x8/64x4
rational
complex
any
void

These types bring ECMAScript in line or surpasses the type systems in most 
languages. For developers it cleans up a lot of the syntax, as described later, 
for TypedArrays, SIMD, and working with number types (floats vs signed and 
unsigned integers). It also allows for new language features like function 
overloading and a clean syntax for operator overloading. For implementors, 
added types offer a way to better optimize the JIT when specific types are 
used. For languages built on top of Javascript this allows more explicit type 
usage and closer matching to hardware.

In theory the following current keywords could be deprecated in the long-term: 
Boolean, Number, String, Object, and the TypedArray objects. Their methods and 
features would be rolled into the new type system.

One of the first complications with types is typeof's behavior. All of the above types 
would return their string conversion including bool. (In my experience 
boolean is seen as verbose among C++ and C# developers. Breaking this part of 
Java's influence probably wouldn't hurt to preserve consistency for the future).

The next few parts cover type features that should be supported. The examples 
aren't meant to be exhaustive but rather show parts of the language that 
require new grammar and discussion.

Support for nullable types.

var foo:uint8? = null;

Support for resizable typed arrays.

var foo:uint8[];
foo.push(1);
var bar:uint8[] = [1, 2, 3, 4];

Support for fixed-length typed arrays:

var foo:uint8[4];
foo.push(0); // invalid
foo.pop(); // invalid
var bar:uint8[4] = [1, 2, 3, 4];

The ability to type any variable including arrow functions.

var foo:uint8 = 0;
var foo = uint8(0); // Cast

var foo:(int32, string):string; // hold a reference to a signature of this type
var foo = (s:string, x:int32) =  s + x; // implicit return type of string
var foo = (x:uint8, y:uint8):uint16 =  x + y; // explicit return type

Function signatures with constraints.

function Foo(a:int32, b:string, c:bignum[], callback:(bool, string) = (b, s = 
'none') =  b ? s : 

Re: Generalize do-expressions to statements in general?

2015-07-16 Thread Herby Vojčík



Mark S. Miller wrote:

I echo this. E is a dynamic language with many similarities with JS,
including a similarly C-like syntax. In E I use
everything-is-a-pattern-or-expression all the time. When I first moved
to JS I missed it. Now that I am used to the JS
statements-are-not-expressions restrictions, I no longer do, with one
exception:

When simply generating simple JS code from something else, this
restriction is a perpetual but minor annoyance. By itself, I would agree
that this annoyance is not important enough to add a new feature.
However, if rather than adding a feature, we can explain the change as
removing a restriction, then JS would get both simpler and more
powerful at the same time. Ideally, the test would be whether, when
explaining the less restrictive JS to a new programmer not familiar with
statement languages, this change results in one less thing to explain
rather than one more.


I like the idea those it seems a bit dense and strange on the first 
look. One breaking change is, though, that before the change, semicolon 
inside parentheses is an error, which often catches the missing 
parenthesis; after the change it is not (and manifests itself only at 
the end of the file; or even two errors can cancel each other and make 
conforming JS but with different semantics).



On Thu, Jul 16, 2015 at 6:38 AM, Andreas Rossberg rossb...@google.com
mailto:rossb...@google.com wrote:

On 16 July 2015 at 15:21, Bob Myers r...@gol.com
mailto:r...@gol.com wrote:

With all do respect, none of this syntax tinkering makes any
sense to me.

I've been programming JS for 15 years and never noticed I needed
a try block that returns a value.

Long ago I programmed in a language called AED that had valued
blockl, which I was quite fond of, but never felt the need for
that in JS for whatever reason.


I've been programming in C++ for 25 years, and didn't have much need
for a try expression or nested binding either.

I've also been programming in functional languages for 20 years, and
need them on a regular basis.

It all depends on how high-level your programming style is. Also,
Sapir Whorf applies as usual.

/Andreas



--
 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: Generalize do-expressions to statements in general?

2015-07-16 Thread Herby Vojčík



Herby Vojčík wrote:



Mark S. Miller wrote:

I echo this. E is a dynamic language with many similarities with JS,
including a similarly C-like syntax. In E I use
everything-is-a-pattern-or-expression all the time. When I first moved
to JS I missed it. Now that I am used to the JS
statements-are-not-expressions restrictions, I no longer do, with one
exception:

When simply generating simple JS code from something else, this
restriction is a perpetual but minor annoyance. By itself, I would agree
that this annoyance is not important enough to add a new feature.
However, if rather than adding a feature, we can explain the change as
removing a restriction, then JS would get both simpler and more
powerful at the same time. Ideally, the test would be whether, when
explaining the less restrictive JS to a new programmer not familiar with
statement languages, this change results in one less thing to explain
rather than one more.


I like the idea those it seems a bit dense and strange on the first

s/those/though/

look. One breaking change is, though, that before the change, semicolon
inside parentheses is an error, which often catches the missing
parenthesis; after the change it is not (and manifests itself only at
the end of the file; or even two errors can cancel each other and make
conforming JS but with different semantics).


On Thu, Jul 16, 2015 at 6:38 AM, Andreas Rossberg rossb...@google.com
mailto:rossb...@google.com wrote:

On 16 July 2015 at 15:21, Bob Myers r...@gol.com
mailto:r...@gol.com wrote:

With all do respect, none of this syntax tinkering makes any
sense to me.

I've been programming JS for 15 years and never noticed I needed
a try block that returns a value.

Long ago I programmed in a language called AED that had valued
blockl, which I was quite fond of, but never felt the need for
that in JS for whatever reason.


I've been programming in C++ for 25 years, and didn't have much need
for a try expression or nested binding either.

I've also been programming in functional languages for 20 years, and
need them on a regular basis.

It all depends on how high-level your programming style is. Also,
Sapir Whorf applies as usual.

/Andreas



--
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

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


Re: revive let blocks

2015-06-25 Thread Herby Vojčík

Hello!

Though this is a kind of syntax is probably macroable, interesting idea 
appeared in my mind regarding let blocks, so I would show it here, maybe 
it can actually be interesting for others as well.



The idea is to use existing let statement and extending it so one can 
include { ... code ... } block in place of last assignment. Hold on for 
a while: this form can merge with do-expressions by using 'let', not 
'do' as the keyword:


  let a = 4, b = 3; // normal let
  let { throw new Error(Throw in an expression); } // let-expression
  let a = 4, b = 3, { a + b } // let-expression with own local lets

The third form is more or less the let-block from the PoV of reader, 
even if in fact is a new do-expression using let keyword with some 
let-assigment local to that block happening before.


I see a 'problem' that I can only distinguish if it is a let-statement 
or let-expression at the end of it, but afaict it does not pose any real 
gotchas for the compiler - it accumulates the assignment and at the 
either make them let-statement and use them for the rest of enclosing 
block or makes it let-expression and use them only locally.


Herby

Kyle Simpson wrote:

Just to wrap this thread up, quoting myself from another thread:

In any case, I won't push my proposal anymore.



But for posterity sake, wanted to make one last comment as to why the various 
suggestions for IIFE's and arrow expressions are inappropriate for the task: 
they change (hijack) the behavior of `return`, `break`, and `continue`. A 
standalone block like `{ let x = 2; .. }` or `let (x = 2) { .. }` can be placed 
anywhere, inside a function, loop, etc, and not hijack these types of 
statements.

I'll be sticking with:

```js
{ let x = 42;

 console.log(The meaning of JS: , x);

}
```

Appreciate the various thoughtful responses.
___
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


When macros will get in, will the core get slimmed in favour of macro-definitions?

2015-06-21 Thread Herby Vojčík

Hello,

in fact, I am just interested on the answer to the question placed in 
the subject, in the light of recent discussion emphasizing minimality.


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


Re: Move es-discuss to discuss.webplatform.org?

2015-06-20 Thread Herby Vojčík



C. Scott Ananian wrote:

No, thank you.​


+1


Email clients are the ultimate forum aggregators.
  --scott

___
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: Unbound arrow functions?

2015-06-20 Thread Herby Vojčík


Dňa 20. júna 2015 19:31:18 CEST používateľ Erik Arvidsson 
erik.arvids...@gmail.com napísal:
 ES'15 provides dedicated method syntax. What are your use cases that
 are
 not covered by methods?

Or, ultimately, by function keyword. If I understand correctly, what you want 
is arrowlike equivalent of what function keyword already provides. If it is 
not the case, just ignore the rest. If it is, the state is, IIRC, that this 
went through the discussion some year ago and the consensus was, no shorter 
form of function should be added just for convenience - only the lexically 
bound one as it actually brings actual added value.

 On Sat, Jun 20, 2015 at 12:13 PM Isiah Meadows impinb...@gmail.com
 wrote:
 
  There already exists a syntax for lexically bound functions, but
 couldn't
  there be an unbound counterpart? I am aware I brought this up
 before, but
  I'm still missing it with smaller methods that still need `this`.
 It's easy
  to macro, but it feels weird to have a lexically bound lambda and
 not an
  unbound equivalent to the anonymous function expression.
 
  aside class=biased
  Also, it's the only reason CoffeeScript still seems attractive in
 any way.
  I know I'm a little opinionated in this area, but I'd rather use ES
 2015 to
  CoffeeScript any day.
  /aside
  ___
  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: revive let blocks

2015-06-18 Thread Herby Vojčík



Benjamin Gruenbaum wrote:

Apart from complicating the engine and the grammar - what advantage does the 
second version have over the first one? Why do you prefer it to the first one? 
(Genuinely asking)

I'm also not aware of any other languages that provide this (although that's 
not a huge issue).


IIRC, Standard ML of New Jersey had a keyword 'local' for this (but it 
was long ago when I has that course in university).


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


Re: revive let blocks

2015-06-18 Thread Herby Vojčík



Benjamin Gruenbaum wrote:

  From: Kyle Simpson get...@gmail.com mailto:get...@gmail.com
To: es-discuss@mozilla.org mailto:es-discuss@mozilla.org
es-discuss@mozilla.org mailto:es-discuss@mozilla.org
Cc:
Date: Thu, 18 Jun 2015 07:34:28 -0500
Subject: Re: revive let blocks
   (function (a, b, c) {
  
   }(2))

  The main disadvantage of that style over the one I'm advocating for
is that it visually separates the variable declaration (`a`) from its
value initialization (`2`).

If that's the problem you can do
```js
((a = 2, b, c) = {

})();
```


Well, I personally think this example is good enough and engines surely 
optimize already (IIFE is here long enough so that it is optimized).



And engines can optimize - but I can see the merit of explicit syntax
for this.


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


Re: @@isConcatSpreadable

2015-06-15 Thread Herby Vojčík



Allen Wirfs-Brock wrote:

On Jun 3, 2015, at 3:46 AM, Leon Arnott wrote:


This reminds me: I feel like the spec should've added
Array.prototype[Symbol.isConcatSpreadable] (value:true,
configurable:false, writable:false), and eliminated the final
IsArray() test from
[22.1.3.11](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-isconcatspreadable).
Would've made the Array#concat() behaviour a little cleaner, in my
opinion.

Unless, perhaps, the point was to leave it open and allow the end-user
to monkey-patch it to false, thus finally fixing Array#concat()
after all these years...? Was that the plan?


Exactly!  ES6 has to preserve the previous semantics for all existing programs, 
including programs that attempted to create Array subclasses in various ad hoc 
manners.

@@isConcatSpreadable exists to allow new ES6-level array subclasses to 
explicitly opt-out of the legacy implicit spread behavior of concat.


So when one actually _wants_ to concat (as, add elements of the 
iterable), it should stop using concat for that and must do something like


 var concatenated = first.slice();
 concatenated.push(...second, ...third, ...fourth);

?


Allen


Herby


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


Re: Existential Operator / Null Propagation Operator

2015-04-07 Thread Herby Vojčík



Kevin Smith wrote:

We should perhaps review this old thread:

https://esdiscuss.org/topic/fail-fast-object-destructuring-don-t-add-more-slop-to-sloppy-mode

for another possible way to avoid non-compositionality.  (Look for the
suggestion about Nil.  It's basically an exotic falsey object which
returns itself for any property lookups or calls.)


Going a bit deeper this way, this thing (changing ref to Nil which 
always returns Nil upon call, construct and get, and getting back 
undefined when value is needed) have nicely separated concerns:


Let's say '?foo', as an unary oper
ator, when foo is a reference, returns Nil when foo is reference to null 
or undefined, otherwise leaves it unchanged. Then:


 ?a.b.c just works,
 ?d() just works,
 new ?e[i]() just works, etc,. since ref is changed to Nil if the thing 
is null/undefined, it propagates through calls and gets, then changes 
itself to undefined value. The priority of ? must be pretty high, 
though, to only apply to nearest token.


Plus, it can be used for normalizing null/undefined to undefined:

 var normalizedFoo = ?foo;

Seems sort of nice that it is separated and there are no special 
operations for ?., ?(, ?[.


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


Re: Existential Operator / Null Propagation Operator

2015-04-07 Thread Herby Vojčík



Christoph Pojer wrote:

it doesn't have to be a bug. It asserts that if a is not
null/undefined, it must have a property b. This can be enforced


Oh, that is completely different semantics. IMNSHO, it goes against DWIM.


through static typing.

On Tue, Apr 7, 2015 at 10:07 AM, Nick Krempelndkrem...@google.com  wrote:


On 7 April 2015 at 18:03, Nick Krempelndkrem...@google.com  wrote:

On 6 April 2015 at 20:01, Jordan Harbandljh...@gmail.com  wrote:

If I want the short circuit in option 1, I'd do `a?.b?.c` to indicate
that, whereas in option 2 if I don't want the short circuit, I'm forced to
use separate variables.


Worth noting that an option 1 `a?.b?.c` differs from an option 2 `a?.b.c`
in that the latter is effectively asserting that if a != null then its b
property is also != null, whereas the former is more lenient in what it
accepts.

Also you are not forced to use separate variables in option 2, you can
just use parentheses: `(a?.b).c` - hence the whole discussion of lack of
transitivity (more correctly, associativity) for option 2. Or did I
misunderstand what you're trying to achieve?


...but thinking about it further, wouldn't you always want the short circuit
semantics? i.e. an option 1 `a?.b.c` is almost certainly a bug?



___
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: Existential Operator / Null Propagation Operator

2015-04-07 Thread Herby Vojčík



Kevin Smith wrote:


  Plus, it can be used for normalizing null/undefined to undefined:
 
   var normalizedFoo = ?foo;
 
  Seems sort of nice that it is separated and there are no special
operations for ?., ?(, ?[.

I agree, that is nice.  But how does Nil get transformed into undefined?


While you do operations like call, construct, get on the reference 
(obtaining another reference), it shortcuts to return Nil. Whenever you 
are not in position to shortcut ref-to-ref (end of expression, for 
example), and you actually needs a value, it just converts to undefined.


?a.b()['foo'] = smalltalk-like
  'a' asRefIn: env) nilRefIfValueNullOrUndefined ref, may be nil
  at: 'b') returns ref, may be Nil
  callWithArguments: #()) returns ref, may be Nil
  at: 'foo') returns ref, may be Nil)
  value now, value is needed, ref needs to dereference

Hopefully this sheds some light. If not, then I don't know how to 
explain it someone with better pedagogy skill must weight in.

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


Re: Existential Operator / Null Propagation Operator

2015-04-06 Thread Herby Vojčík



Christoph Pojer wrote:

Tim Yung and I have hacked on a reference implementation for the
Existential Operator using esprima-fb and jstransform: a?.b

Example:

`a?.b` =  `(a == null ? void 0 : a.b)`
`a?.b.c` =  `(a == null ? void 0 : a.b.c)`

This must also make sure that `a` only gets evaluated a single time.

Based on previous discussions on es-discuss and TC39, it seems that
this was tabled for ES6. I think now is a good time to bring it up for
ES7. There is precendence for this feature in other languages - it was
recently added to C# and Hack and has always been in CoffeeScript.
TypeScript is waiting for TC39:
https://github.com/Microsoft/TypeScript/issues/16

In the past, this topic has invited a lot of bikeshedding, but I'd
like us to look past this. Several communities within and outside the
JS community have identified the need for this operator. My
understanding is that a decision needs to be made about whether the
operator should short-circuit additional invocations in the call chain
if the operand is null (aka. null propagation).

For example, if `a` is null, should `a?.b.c`:

1) evaluate to `(void 0).c` and throw a TypeError?
2) short-circuit at `a` and return `void 0`?


I liked the result of using a Null Pattern inside and materializing it 
outside, which once seemed to be plausible, with that `a?.b.c` would be 
`void 0` of course. I don't remember on what it all died back then (yes, 
I have a bias, I wanted a true null pattern, AWB than said it is good 
inside but not really good as first class person).



It appears that C# chose option #2 whereas Hack and CoffeeScript chose
option #1. Our current implementation chose option #1 but we'd be
happy to build a reference implementation for option #2.

I recall that another issue was that of transitivity. Right now,
(a.b).c and a.b.c are equivalent. (a?.b).c and a?.b.c would not be
equivalent expressions. I think we need some input from the people on
this list about whether this is okay or why we value transitivity for
this operator.

If we can come to an agreement on the existential operator for member
expressions, we would also be setting a precedent for other features
of the same family. For example, existential call expressions: `fn?()`
which would conditionally invoke `fn`.

esprima-fb change: https://github.com/cpojer/esprima/tree/existential-operator
jstransform change:
https://github.com/yungsters/jstransform/tree/existential-operator

Previous discussions on es-discuss:
* https://esdiscuss.org/topic/the-existential-operator
* 
https://esdiscuss.org/topic/specifying-the-existential-operator-using-abrupt-completion
* https://esdiscuss.org/topic/sept-18-tc39-meeting-notes


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


Re: (x) = {foo: bar}

2015-02-01 Thread Herby Vojčík



Brendan Eich wrote:

Mark Volkmann wrote:

My apologies. I meant to say that Traceur doesn't support returning a
literal object from an arrow function with syntax like this:

let f = x = ({foo: bar});

However, I just tested it again and it works fine. I could swear this
didn't work a few months ago. Maybe it was fixed recently. I'm happy!


Cool -- you are supporting Caitlin's thesis that we can pedagogue around
the footgun. I hope so.

Still leaves
http://wiki.ecmascript.org/doku.php?id=strawman:block_vs_object_literal
as an option for ES7. Comments welcome.


A crazy idea:

(a, b) { body }
(a, b) = expr /* always expr context */

the only problem I quickly see is to distiguish (a) { body }, but IMHO 
there is the same lookahead need for distiguishing (a) = something today.



/be


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


Re: (x) = {foo: bar}

2015-02-01 Thread Herby Vojčík



Marius Gundersen wrote:

I don't see how wellLabeledStatement will protect against object
literals with shorthand properties, like (x, y, z) = {x, y, z}.

The solution to the block vs object problem today is to wrap the object
in parenthesis, but not the block. The only alternative that is easy for
humans to understand and not ambiguous for machines is to wrap or prefix
the block, but not the object, for example with do:

x = do {
   let a = 5;
   return a*x;
}


Yeah, this is good.

Even if do expression won't get in, if one could clearly tell the intent 
(block vs. expression), it would make things easier to work with.


= expr / = do block is less ambiguous then = expr / [nothing] block I 
posted earlier.




AFAIK do expressions are not in ES6, but might be in ES7.

Marius Gundersen

On 6 Jan 2015 19:42, Brendan Eich bren...@mozilla.org
mailto:bren...@mozilla.org wrote:

Sorry, sent too soon.

Dean Landolt wrote:

If it's too late to properly vet a change which narrowly
excludes from arrow bodies any `LabeledStatement` that isn't a
`WellLabeledStatement`, would it be feasible to simply exclude
any `LabeledStatement` for now? I doubt there's much code in the
wild that would be affected by this change -- certainly not yet.
That'd buy plenty of time to add back proper support for
`WellLabeledStatement` arrow bodies in es7.


The ES6 grammar has not been refactored per my old strawman. It has
no WellLabeledStatement non-terminal.

For ES6, we would need another production parameter to FunctionBody,
FunctionStatementList, and StatementList (at least) by which to
restrict a ConciseBody : { FunctionBody } such that the FunctionBody
: FunctionStatementList (via FunctionStatementList :
StatementList[opt], StatementList StatementListItem, etc.) doesn't
start with a LabelledStatement.

Cc'ing Allen and Waldemar for their thoughts.

/be
_
es-discuss mailing list
es-discuss@mozilla.org mailto:es-discuss@mozilla.org
https://mail.mozilla.org/__listinfo/es-discuss
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: classes and enumerability

2015-01-22 Thread Herby Vojčík



Allen Wirfs-Brock wrote:


On Dec 24, 2014, at 1:49 PM, Kevin Smith wrote:


Here is the summary:
Total Files Read: 11038
Files Containing Explicit 'enumerable: false': 149
Occurrences of 'enumerable: false' (and variants): 206


I love this kind of analysis - thanks!

My interpretation of this data is that non-enumerability isn't
important enough to bother with in the vast majority of cases. It
*may* still be that non-enumerability is the least-surprise option for
class methods, but certainly users don't care enough about the issue
currently to bother with typing in enumerable: false.

I'm still concerned about the refactoring hazard argument. I think the
idea is that if I change some ES5-style class into an ES6-style class,
then I need to have good unit tests already in place to make sure that
non-enumerability won't break things. Otherwise, I can't do the refactor.


Let's drill deeper into this concern...

There are two parts of dealing with a class-abstraction, the definition
the class and consuming instances of the class. Let's look at the
enumerability impact on both of those.

Class definition: In an ES5-level class abstraction library, changing
the enumerability of methods might have an impact on class creation, if
the attraction library does something like method copying using for-in.
However, what we are talking about is converting from an ad hoc (and
possibly library provided) ES5 class abstraction to using actual ES6
class definition. Class definitions don't depend upon reflection of
properties to actually create the class. So, I don't think we have
anything to worry about on the class definition side. Enumerability of
properties is irrelevant.

Class consumption: It pretty much comes down to whether or not consumers
of class instances in ES5 use for-in with or without hasOwnProperty
filters to enumerate the properties of class instances. If their ES5
code uses hasOwnProperty to filter out methods, then the fact that ES6
methods are non-enumerable will make no difference. On the other hand,
if consumers of these ES5 class instances are doing for-in enumerations
and want to see inherited methods then there would be an issue. But,
other than for meta programming, it hard to imagine why they would
actually want tfor-in to see any methods.

Some folks at Auburn University have been studying a large corpus of
JavaScript code, see http://munawarhafiz.com/research/jssurvey/
On of the things they've look at is use of for-in and hasOwnProperty.
Take a look at the data shown on that page for for-in usage and read
sections X and XI in the accompany paper.

Personally, I have always believed we are going down the wrong path by
switching (from the original max-in class design) to making methods
defined within a class definition enumerable.


Yes, please, if possible, go back to non-enum methods. I was writing at 
that time as well, but things ended up enumerable. I even cited a 
real-world example (Amber objects used in jQuery API as options 
objects), where enum methods broke the functionality, but non-enum 
methods allowed things to work.



The only real model of class-like abstractions that has always and
universally been a part of JS is the model that the built-in
constructors consistently follow. The ES6 class definition model was
intended to exactly mirror that built-in model. My vision for it was
that future JS programmers should never need to worry about whether a
class was provided by a built-in or from a library or was a local part
of the application, because they all worked the same.

By make class defined methods enumerable, we parted from that simple
vision and instead seem to follow the remediation path that current and
legacy JS programmers had to follow because the language did not give
them the capabilities they need to define classes just like the
built-ins. We're tinking too much about the past and not enough about
the future.

Allen


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


Re: new instantiation design alternatives

2014-09-17 Thread Herby Vojčík

I agree, the thread was about defaults when no super call is present.

Allen Wirfs-Brock al...@wirfs-brock.comnapísal/a:

Unfortunately, I think the super in function header discussion is mostly a 
distraction and not really helping focus the discussion on  the core issues.

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


Re: new instantiation design alternatives

2014-09-17 Thread Herby Vojčík


Claude Pache claude.pa...@gmail.comnapísal/a:


For instance, if I wanted to support to be called through the legacy 
`SuperConstructor.call(this, ...args)` trick in addition to be new’d, I'd 
rather try the following:

constructor(x, y) {
if (new^)
this = new super(x);
else
super.constructor(x);
this.y = y;
}

Oh, this is really bulky.

Makes me think of fixing it by some slight magic. Like, adding modifier to 
method deginition to say it is a constructor (new keuword before opening left 
brace) and keeping stack of new^s in thread-local storage which wull be used in 
new-tagged methods, even if [[Call]]ed.

But that is not a nice solution at all. :-/

The point here is that the purpose of the constructor method is not only 
allocation, but also (and primarily) initialisation.

—Claude

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


Re: new instantiation design alternatives

2014-09-17 Thread Herby Vojčík



Domenic Denicola wrote:



On Sep 17, 2014, at 7:10, Kevin Smith zenpars...@gmail.com 
mailto:zenpars...@gmail.com wrote:




That seems fine. Enabling different behaviour for called vs.
constructed should only be used to explain the builtins; user
code should not do so themselves. So it makes sense to me that
those trying to do that would get punished with having to type
more.


Yes, but if we guide users toward this = new super, we actually 
change the current paradigm where the constructors can be called or 
new'd.


As an example, this:

function C() { B.call(this) }

functions perfectly well as an object initializer, with or without new.


That's not true, is it? Assuming someone (e.g. B) actually assigns a 
property of `this`, an error will occur (or worse, a global will be 
created, in sloppy mode).


Maybe Kevin meant can be new'd to create and initialize, and can be call'd 
just to
initialize the existing one.

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


Re: new instantiation design alternatives

2014-09-15 Thread Herby Vojčík
This is probably not a constructive feedback, but thanks for changing 
super semantics in constructors, as it's fixing the new/super difference 
of previous design.


Herby

Allen Wirfs-Brock wrote:

At the last TC39 meeting (
https://github.com/rwaldron/tc39-notes/blob/master/es6/2014-07/jul-30.md#44-instantiation-reform-review-create-design-rationale-and-possible-alternatives
https://github.com/rwaldron/tc39-notes/blob/master/es6/2014-07/jul-30.md
and
https://github.com/rwaldron/tc39-notes/blob/master/es6/2014-07/jul-31.md#44-follow-up-instantiation-reform-create
) we agreed to a general direction to try for a new object instantiation
design to replace @@create.

Since then I have gotten feedback and had design discussions with a
number of individuals. This has lead to a number of refinements of the
core design and one remaining point where there are strong contrary
positions. The point of contention is about whether or not a subclass
construction ever implicitly calls its superclass constructor.

https://gist.github.com/allenwb/291035fbf910eab8e9a6 summaries the main
syntactic changes since the meeting and provides rationales them. These
features are common to both alternates. this is a good place to start,
after reading the meeting notes.

I have prepared two longer Gists that outline the two alternatives
designs, presents design rationales, and provides usage examples for a
number of likely use cases. Note that there is more commonalities then
differences among the two alternatives. the syntactic choices and
semantics of [[Construct]] are the same for both.

These two Gist have parallel construction for easy comparison. I suggest
approaching this is by first readying through one of the Gists and then
doing a side by side read through of the alternative to see the
differences in the designs and usage.

https://gist.github.com/allenwb/5160d109e33db8253b62 with implicit super
construct if no local allocation
https://gist.github.com/allenwb/53927e46b31564168a1d explicit super
construct required if no local allocation

I appreciate it if major constructive feedback on any of these documents
were made via Gist comments.

Allen

___
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: new instantiation design alternatives

2014-09-15 Thread Herby Vojčík



Kevin Smith wrote:

Well, what I'm trying to point out is that it's always an error to set
this if new^ is undefined.  So it's kind of strange to force the
user to explicitly write that conditional:

 constructor(x, y) {
 if (new^)
 this = new super(x);
 this.y = y;
 }

With the header approach, it's taken care of:

 constructor(x, y) : super(x) {
 this.y = y;
 }

(using colon just to avoid bikeshedding)


Isn't the latter (since it specifies : super(x)) actually identical to

constructor(x, y) {
this = new super();
this.y = y;
}

IOW, isn't it I am constructor only and will throw if {[Call]]ed)?

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


Re: ... A community is writing the spec...

2014-09-10 Thread Herby Vojčík



Axel Rauschmayer wrote:

Now is second half of 2014, and lots of issues are not closed yet,
from what I see.


The spec already looks pretty complete to me and Traceur and TypeScript
do a pretty good job of letting you use ES6 today.

As previously announced here, the current schedule is to be finished by
the end of the year, to start the publication process in March 2014 and
to have a standard by June 2014.


They already happened. Did you mean 2015?


I got delusioned as well.

Isn't the model of big new editions of spec over; in the times we live
now, with two-week frequent releases? I think ES6 will never see the
light when taken from this approach. That's why, shouldn't the release
policy be changed so that:


It has already changed, but not for ES6. ECMAScript 7 and later will
have fixed release dates. Only features that are ready at a given date
will be included.


Hallelujah!


Background: https://github.com/tc39/ecma262

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


Herby

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


Re: Proposal to fix super and new inconsistency, future-proofing broader uses of new operator

2013-12-10 Thread Herby Vojčík

[ reposting, since there was no reply to original posting ]
[ thread starting here: 
https://mail.mozilla.org/pipermail/es-discuss/2013-August/033089.html ]


Allen Wirfs-Brock wrote:
 An interesting proposal, but I'm not yet sold. Here are some of the
 issue I see:

 1) By newing a function an ES programmer is expressing a clear intent
 to use the body the body of the function as part of the instantiation
 process. It would be counter intuitive to not execute the body of a
 constructor function when performing a new:

 function C() {console.log(C constructed)};
 ...
 //code somewhere else
 C.prototype.constructor = function () {}

BTW this is the first case from my original post. How often this 
example happens in real world (without changing C.prototype before this 
assigment)? Because if C.prototype is changed, legacy semantics is used.


 ...
 //back in the original script
 new C; //whoa why wasn't the constructor called

Well,
  new (class extends C); // whoa why wasn't C called

This happens in actual state as well, though it is a little more hidden.

I am convinced that always, except very special cases
  new C
and
  new (class extend C)
should produce nearly* same instances, behaviourally. It is not the 
case, though.


* they should only differ in meta issues like if their __proto__s are 
equal or which inherits from which one, what they return to 'foo 
instanceof Bar' for some edge cases, etc.


 A class declaration is similar. It defines (either explicitly or
 implicitly) the body of the class constructor. It would be equally
 counter intuitive to not use that body when newing a class.

It is different here (well, that is matter of PoV, I have different 
one). In class, you do not define body of any constructor-function, you 
define body of 'constructor' method. It is just a convenience that 
this method is also reachable by using the class itself (That its 
.prototype is set up accordingly can be seen as just a result of this 
convenience - if class would be represented by different object, that 
object would have its .prototype set).


(well, I understand it is not just a convenience, the constructor 
should represent the class because of SuperClass.apply(this, 
arguments) legacy subclassing pattern, thus I see it as a workaround, 
not as a defining feature; other than this, class could be fine with any 
other object, provided it has .prototype, @@create and new(...args) 
would run Foo[@@create]().constructor(...args))


There is no constructor-function (if you look at syntax). There is class 
declaration, where one of the methods can be called 'constructor' and is 
used to initialize an instance of the class. If you do not define it, 
the one up the proto chain will be used. So this really behaves as if it 
was a normal method (in the default case, when you do not rewrite 
TheClass.prototype.constructor).


With the presented proposal, where new(...args) does (sans errors)
  Foo[@@create]().constructor(...args)
there is even little point of actually defining the default constructor 
that just calls super (the only reason why it is really needed is that 
something must be reachable by using class itself, and using constructor 
method in all cases is consistent behaviour plus the legacy workaround).


 2) Some classes may not wish to expose an instantiation capability via
 their instances. ES6 GeneratorFunctions are a good example this. See
 lower right part of the diagram at
 http://people.mozilla.org/~jorendorff/es6-draft.html#sec-15.19.3 . Each
 GeneratorFunction has an associated prototype that is used by all of
 that GeneratorFunction's instances. However, the prototype does not have
 a 'constructor' property. This means that passing someone a generator
 instances doesn't give them the capability to instantiate additional
 instances of the same GeneratorFunction. Whether class instances should

Well, we talk two things here.

First, that GeneratorFunctions' prototypes (thus their instances) do not 
have .constructor. The diagram shows these instances have 
Object.prototype in their proto chain. Thus, the first thing, whether 
they can be safely instatiated with the presented proposal (which is the 
question that must be answered) is true: 
GF[@@create]().constructor(...args) @@creates appropriate object and 
calls empty .constructor(...args) inherited from Object.prototype.


The second thing is 'some classes may not wish to expose an 
instantiation capability via their instances' and using 
GeneratorFunctions as an example of this.


This thing is, as I pointed in Issues down in my original post, with the 
present proposal no class in general exposes an instantiation 
capability; because in general, 'constructor' is plain method. Yes, in 
cases where constructor method is also used as newable (legacy 
constructor functions and `class`), default value of .constructor 
exposes instantiation capability, though whenever you change it, it 
stops to expose it.


So, the fact that 

Re: Proposal to fix super and new inconsistency, future-proofing broader uses of new operator

2013-09-04 Thread Herby Vojčík



Allen Wirfs-Brock wrote:

An interesting proposal, but I'm not yet sold. Here are some of the
issue I see:

1) By newing a function an ES programmer is expressing a clear intent
to use the body the body of the function as part of the instantiation
process. It would be counter intuitive to not execute the body of a
constructor function when performing a new:

function C() {console.log(C constructed)};
...
//code somewhere else
C.prototype.constructor = function () {}


BTW this is the first case from my original post. How often this 
example happens in real world (without changing C.prototype before this 
assigment)? Because if C.prototype is changed, legacy semantics is used.



...
//back in the original script
new C; //whoa why wasn't the constructor called


Well,
  new (class extends C); // whoa why wasn't C called

This happens in actual state as well, though it is a little more hidden.

I am convinced that always, except very special cases
  new C
and
  new (class extend C)
should produce nearly* same instances, behaviourally. It is not the 
case, though.


* they should only differ in meta issues like if their __proto__s are 
equal or which inherits from which one, what they return to 'foo 
instanceof Bar' for some edge cases, etc.



A class declaration is similar. It defines (either explicitly or
implicitly) the body of the class constructor. It would be equally
counter intuitive to not use that body when newing a class.


It is different here (well, that is matter of PoV, I have different 
one). In class, you do not define body of any constructor-function, you 
define body of 'constructor' method. It is just a convenience that 
this method is also reachable by using the class itself (That its 
.prototype is set up accordingly can be seen as just a result of this 
convenience - if class would be represented by different object, that 
object would have its .prototype set).


(well, I understand it is not just a convenience, the constructor 
should represent the class because of SuperClass.apply(this, 
arguments) legacy subclassing pattern, thus I see it as a workaround, 
not as a defining feature; other than this, class could be fine with any 
other object, provided it has .prototype, @@create and new(...args) 
would run Foo[@@create]().constructor(...args))


There is no constructor-function (if you look at syntax). There is class 
declaration, where one of the methods can be called 'constructor' and is 
used to initialize an instance of the class. If you do not define it, 
the one up the proto chain will be used. So this really behaves as if it 
was a normal method (in the default case, when you do not rewrite 
TheClass.prototype.constructor).


With the presented proposal, where new(...args) does (sans errors)
  Foo[@@create]().constructor(...args)
there is even little point of actually defining the default constructor 
that just calls super (the only reason why it is really needed is that 
something must be reachable by using class itself, and using constructor 
method in all cases is consistent behaviour plus the legacy workaround).



2) Some classes may not wish to expose an instantiation capability via
their instances. ES6 GeneratorFunctions are a good example this. See
lower right part of the diagram at
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-15.19.3 . Each
GeneratorFunction has an associated prototype that is used by all of
that GeneratorFunction's instances. However, the prototype does not have
a 'constructor' property. This means that passing someone a generator
instances doesn't give them the capability to instantiate additional
instances of the same GeneratorFunction. Whether class instances should


Well, we talk two things here.

First, that GeneratorFunctions' prototypes (thus their instances) do not 
have .constructor. The diagram shows these instances have 
Object.prototype in their proto chain. Thus, the first thing, whether 
they can be safely instatiated with the presented proposal (which is the 
question that must be answered) is true: 
GF[@@create]().constructor(...args) @@creates appropriate object and 
calls empty .constructor(...args) inherited from Object.prototype.


The second thing is 'some classes may not wish to expose an 
instantiation capability via their instances' and using 
GeneratorFunctions as an example of this.


This thing is, as I pointed in Issues down in my original post, with the 
present proposal no class in general exposes an instantiation 
capability; because in general, 'constructor' is plain method. Yes, in 
cases where constructor method is also used as newable (legacy 
constructor functions and `class`), default value of .constructor 
exposes instantiation capability, though whenever you change it, it 
stops to expose it.


So, the fact that GeneratorFunctions do not define .constructor in their 
.prototype is fine.


Or, IOW, I never proposed that .constructor is mandatory in each 
.prototype. It just has to be on proto 

Proposal to fix super and new inconsistency, future-proofing broader uses of new operator

2013-08-31 Thread Herby Vojčík

Hello!

PROBLEM


In the present state of the spec, there is little inconsistency between 
behaviour of new and super.


What these operation roughly do is:

  new Foo(...args) is
Foo.call(Foo[@@create](), ...args)
  super(...args) inside constructor is
__superclassproto__.constructor.call(this, ...args)

This is elegant and consisten solution - super behaves as in any other 
method - calling superclass's version of itself.


Since Foo.prototype.constructor is set to Foo by default, no 
inconsistency is observed in default case - super(...args) calls the 
same function from subclass of Foo and in new Foo.


But if constructor is changed (or deleted / not defined), inconsistency 
appears - new still calls Foo, but super calls different function (or 
fails if there is no .constuctor in proto chain).


My gut feeling is that new Class and super in SubClass should do the 
same thing. Also, if this IMO bug begins to be exploited, to have 
different initialization of own instance versus subclass one, there is 
no way back.


SOLUTION


There is elegant solution for this by redefining new to do roughly:

  new Foo(...args) is
Foo[@@create]().constructor(...args)

Compared to previous semantics, this is much cleaner and understandable, 
and in par with super philosophy of treat 'constructor' as just another 
method.


For default cases, this works identically with the formed definition.

For `class` keyword, if you change constructor method of an existing 
class, this semantics nicely implements your intent - to change the way 
howe class Foo is initialized (in both new and super).


Remaning scenario is changed .constructor of constructor function.
Here, it can be changed directly (you change .constructor of existing 
.prototype) or indirectly (you change .prototype of the constructor 
function). Both would break existing web.


The silent assumption of this proposal is, that the former case 
(changing .constructor of default .prototype) is rare if it ever 
appears, though I did not search for this.


The second case is much more common: one redefines .prototype of a 
function, but does not define .constructor there (there was no real 
need). I would propose guard against this case - whenever the .prototype 
of a function is changed, the new would use old, legacy semantics. 
Constructor functions with non-changed .prototypes, as well as `class`es 
(which have .prototype non-writable) would work fine with the new, 
cleaner semantics.


FUTURE PROOFED BROADER NEW


This change decoupled the need of the Foo in `new Foo` being callable - 
so the new semantics of new allows any object having @@create defined to 
be usable inside new - the initialization of the instance is nothing 
more than just calling 'constructor' method with appropriate args, so 
the new instance is responsible for initializing itself, no matter who 
was its creator/allocator.


ISSUES


1. It is not known if the case of changing .prototype.constructor 
without changing .prototype itself on legacy constructor functions is 
really rare or it has its legitimate use and is spread.
2. Instance does not know its creator/class (you cannot do generic 'new 
this.constructor(...args)').


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


Re: Make class constructors work with [[Call]] too?

2013-07-06 Thread Herby Vojčík



Domenic Denicola wrote:

From: Rick Waldron [waldron.r...@gmail.com]


Regardless, I support your claim. It's not that library authors use this 
pattern in all constructor definitions, all the time—it's a pattern used by 
responsible authors when creating constructors to ensure user code will just 
work, whether invoked

  with or without new.

Indeed. I actually first thought of it in the context of how we want the DOM to 
work, now that there's a push for actual constructors. I thought the DOM types 
should probably work like the built-in types do (viz. `Object`, `Array`, 
`Function`, and `RegExp`, albeit not `Date` as Claude points out). And if were 
to specify something about DOM constructors generally, we should make sure it 
follows ES6 class syntax.


Back to Domenic's original post... I would also like this to be the default 
semantics for class, but wonder if that will bite program code that assumes 
(incorrectly, if it doesn't abide strict mode) these have th

e same invocation semantics:


I see what you're saying, but I think classes already have minor tweaks (e.g. 
default super-invocation and the existence of super) that one more wouldn't 
hurt. At least, that was my logic :P


Going by this logic, one can argue for other tweaks instead - for example - I 
repeat myself - to fix the super vs. new disrepancy by introducing saner 
sematics for new Class (calling F.prorotype.constructor instead of F, thus 
doing (more or less, with special non-typeof-object exceptional case) 
`F[@@create].constructor(...args)` instead of `F.call(F[@@create], ...args)` 
and be aligned with super). And one can easily include [[Call]] into it by 
making F itself being compiled into `return new F(...args)` (and include the 
working code itself in the constructor).

Herby

P.S.: In fact, I would say, for future, the new semantics 
(F[@@create].constructor(...args)) should be the default for any object usable 
with new, since it is totally generic (no need for F.c
all to work; just having [@@create] and produce thing with .constructor) and 
leaving the old one for legacy constructor functions.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Set some, every, reduce, filter, map methods

2013-03-30 Thread Herby Vojčík

Definitely, +1.

Also, add reduceRight as well, even if it would only do the same as reduce.

Peter Michaux wrote:

In another thread, I'm told there is currently no plans to add the
following to Set.prototype.

some
every
reduce
filter
map

These seem like very natural additions and the type of operations that
one would want to do on sets.

Peter
___
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: Set some, every, reduce, filter, map methods

2013-03-30 Thread Herby Vojčík

Well, why not, but forEach, some, every, reduce[Right] and filter are very 
natural operations useful for _any_ collection (map is harder). If Set has 
forEach, it should have these as well. Of course, iterators could have them as 
well.

It is strange if Array and iterators would have it, but other collections would 
not. The code that takes a collection as a parameter and calls some, every, 
filter etc. on it would break, instead of doing the job on Set (at least some, 
every and reduce family can be transparently used; and I would argue for filter 
as well - it returns subcollection that understands the collection protocol 
(@@iterator, values, forEach, some, every, filter, reduce, reduceRight)).

Herby

P.S.: What should generic collection contract consist of in ES6? I would say 
the except those named above only needed addition is isEmpty, length/size, and 
possibly clear as well as copy/clone (slice is not right for Set/Map).

Erik Arvidsson wrote:

I said this in the other thre

ad but I don't mind repeating myself. A

better way forward is to provide these for iterators.

mySet.values().some(func)
mySet.values().every(func)
mySet.values().reduce(func)
new Set(mySet.values().filter(func))
new Set(mySet.values().map(func))

I'm not opposed to adding these to Set and Map but I think it is more
important to define these using iterators first since it scales better
to new collection types.


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


Re: Constructors need to be able to recognize uninitalized instances(?)

2013-03-18 Thread Herby Vojčík
I think the idea of detecting if you have initialized or noninitialized 
instance at runtime is very unhappy idea.


You know when it is called as an initializer (2, 4 below) and when not 
(1 below). 3 below is legacy way of doing super - it can be simply replaced.


And there is also no breaking compatibility cost - so far, there was no 
API to distinguish this; so once it is added, it can be safely specified 
that initializer context is only 2 and 4.


Herby

Axel Rauschmayer wrote:

[Referring to Allen’s slides:
http://wiki.ecmascript.org/lib/exe/fetch.php?id=meetings%3Ameeting_jan_29_2013cache=cachemedia=meetings:subclassing_builtins.pdf
http://wiki.ecmascript.org/lib/exe/fetch.php?id=meetings%3Ameeting_jan_29_2013cache=cachemedia=meetings:subclassing_builtins.pdf
]

Is this really true?

I can see four ways of invoking a constructor function C:

1. As a function: C(...)
2. Via `new`: new C(...)
3. Via `call`: C.call(this, ...)
4. Via `super`, in a sub-instance, as a method (similar to #3):
super.constructor(...)

C[@@create] is only invoked during #2 (by the `new` operator). Thus, the
constructor’s role is always: set up an uninitialized instance. You
could add a check against an instance being initialized twice, but that
doesn’t seem to be what the slides are about.

The slides mention one use case: What if you want to have a function Foo
that can be either called as a function or as a constructor? You can’t
detect the difference if Foo is inside a namespace object. That is, you
want to distinguish #1 from all others, but #1 could happen to a
namespaced C. Observations:

– Does recognizing whether `this` is initialized really help here? Isn’t
it more about checking whether `this` is an instance of C?

– I’ve always considered this to be more of an anti-pattern for
non-builtin code. Thus, it seems useful to support a check, but only so
that namespaced constructors can avoid accidentally polluting the
namespace object.

– Won’t namespace objects go away with modules?

Thanks!

Axel

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

home: rauschma.de http://rauschma.de
twitter: twitter.com/rauschma http://twitter.com/rauschma
blog: 2ality.com http://2ality.com

___
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: Comments on “Making Built-in Objects Subclassable”

2013-03-18 Thread Herby Vojčík



Axel Rauschmayer wrote:

A few more thoughts:

- This marks the end of prototypal inheritance in JavaScript (not
complaining, just stating a fact). Putting @@create in constructors C
makes a lot of sense, but it could, in principle, also be put into
instance prototypes C.prototype. Then Object.create(proto) could use
@@create to create the instance whose prototype is proto.


The identifier create is probably used in lots of other places, so this 
is non-starter, but if not, it could be simply reused, so that:


  Ctr.create(proto, [descriptors])

does

  newobj = Ctr[@@create]();
  newobj.__proto__ = proto;
  Object.defineProperties(newobj, descriptors);

It is semantically compatible with what Object.create does now.
In fact, if somewhere inside implementation of Object.create one would 
use this[@@create] to create new instance, and it was moved to 
Function.prototype, it could be used as is.



Axel


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


Re: Comments on “Making Built-in Objects Subclassable”

2013-03-18 Thread Herby Vojčík



Herby Vojčík wrote:



Axel Rauschmayer wrote:

A few more thoughts:

- This marks the end of prototypal inheritance in JavaScript (not
complaining, just stating a fact). Putting @@create in constructors C
makes a lot of sense, but it could, in principle, also be put into
instance prototypes C.prototype. Then Object.create(proto) could use
@@create to create the instance whose prototype is proto.


The identifier create is probably used in lots of other places, so this
is non-starter, but if not, it could be simply reused, so that:

Ctr.create(proto, [descriptors])

does

newobj = Ctr[@@create]();
newobj.__proto__ = proto;
Object.defineProperties(newobj, descriptors);


Sorry for replying to myself, but another possibility is to add proto 
and descriptors parameters to IIRC parameterless @@create. Object.create 
would thus just point to Object[@@create] and others could be create 
similarly: Array[@@create](myprototype, mydescriptors);



It is semantically compatible with what Object.create does now.
In fact, if somewhere inside implementation of Object.create one would
use this[@@create] to create new instance, and it was moved to
Function.prototype, it could be used as is.


Axel


Herby

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


Re: Nuking misleading properties in `Object.getOwnPropertyDescriptor`

2013-03-14 Thread Herby Vojčík



Tom Van Cutsem wrote:

[+Allen]

2013/3/13 Nathan Wall nathan.w...@live.com mailto:nathan.w...@live.com

However, as a matter of principle, my argument is that
`Object.getOwnPropertyDescriptor` should, at the bare minimum,
return a descriptor that can be known to work in
`Object.defineProperty`.  If `Object.defineProperty` doesn't accept
it, then you `getOwnPropertyDescriptor` didn't really give me a
valid descriptor.

I think that this behavior (1) limits the creativity of developers
to define properties like `Object.prototype.get`, (2) is a potential
stumbling block, (3) has no real benefit -- really, there's not
anything positive about this behavior, and (4) forces developers who
want to support `Object.prototype.get` to add an extra layer of
cleaning before using `defineProperty`.


While the monkey-patching of Object.prototype (don't do that!) is
still the culprit, I agree that it would have been better if
defineProperty looked only at own properties of the descriptor. I
No, there are legitimate uses of Object.create(descriptorTemplate) with 
descriptors.



almost always think of descriptors as records rather than objects.
Similarly, perhaps Object.getOwnPropertyDescriptor should have returned
descriptors whose [[prototype]] was null.


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


Re: Nuking misleading properties in `Object.getOwnPropertyDescriptor`

2013-03-10 Thread Herby Vojčík
Yes, this was in this list some three-four months ago. There were 
answers like JS is this way dynamic, playing with Object.prototype hurts.


I proposed that return value from Object.getOwnPropertyDescriptor should 
inherit from well well-known frozen object with all the default set. 
Back, then no-one seemed to be interested.


Herby

Nathan Wall wrote:

Given that `defineProperty` uses properties on the prototype of the 
descriptor[1] and `getOwnPropertyDescriptor` returns an object which inherits 
from `Object.prototype`, the following use-case is volatile:

 function copy(from, to) {
 for (let name of Object.getOwnPropertyNames(from))
 Object.defineProperty(to, name,
 Object.getOwnPropertyDescriptor(from, name));
 }

If a third party script happens to add `get`, `set`, or `value` to 
`Object.prototype` the `copy` function breaks.

 Object.prototype.get = function() { };

 var x = { foo: 1 };
 var y = { };
 copy(x, y); // TypeError: property descriptors must not specify a value or
 // be writable when a getter or setter has been specified

It's misleading that you can't trust `getOwnPropertyDescriptor` to give you a 
descriptor which you can use to define a property with `defineProperty`.

A script which doesn't use `defineProperty` could very well define a `get` 
property on `Object.prototype`, unknowingly breaking other scripts which do use 
`defineProperty`. This is a hazard in the language.

I think one of the following would be an appropriate solution:

(1) Nuke the special properties (`get`, `set`, and `value` when any of them is not 
defined) on a descriptor returned by `getOwnPropertyDescriptor` which shouldn't be inherited 
through the descriptor's prototype. By nuke them, I mean specify that they be defined 
as `undefined`, much like `callee` and `caller` in strict mode. (I don't think strict mode is 
required in this case, though, since I highly doubt anyone could be relying on this behavior.)

(2) Use the introduction of `Reflect.defineProperty` as an opportunity to fix 
this function to only inspect own properties on the property descriptor so that the 
descriptor's prototype doesn't matter. This is similar to the addition of `Number.isNaN` 
to fix the broken `isNaN`.

Nathan


[1] https://mail.mozilla.org/pipermail/es-discuss/2012-November/026705.html 

___
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: Array subclassing, .map and iterables (Re: Jan 30 TC39 Meeting Notes)

2013-02-14 Thread Herby Vojčík



Nathan Wall wrote:

Hey Allen, thanks for clarifying.

What will happen to other Array methods which currently return
Arrays? `filter` is the primary one that comes to mind. Will
`uint32array.filter((v) =  v != 0)` return a Uint32Array? (I think
it should behave the same way `map` does.)


I know I already said that, but I repeat: `map` transforms elements, 
`filter` just selects a subset. Therefore I am 100% for `filter` doing 
the same kind of collection as the receiver. Bit not necessarily for `map`.


So I think, not, `filter` should not behave same as `map`.


Additionally, what will happen with the return values of `slice`,
`splice`, and `reverse`?.. not to mention `concat`, which I know is a
much more complex beast.


I think `filter` should behave the same as `slice`, `splice`, `reverse` 
and `concat`. They have clear rationale to use same kind of container.



Nathan


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


Re: Are frozen Objects faster ?

2013-02-14 Thread Herby Vojčík



Kevin Gadd wrote:

Frozen and sealed objects are both dramatically slower in most JS
engines I've tested. In the ones where they're not dramatically slower
they are never faster.

The last time I asked on the mozilla and v8 bug trackers I was
informed that there is no plan to optimize for these features and that
the design of the respective JS engines would make such optimizations
difficult anyway.

(I find this extremely unfortunate.)


I, on the other hand, find it fortunate. Otherwise, some people would 
prematurely freeze objects to gain speed. It would be same 
deldisaster/del akwardness as v8 did with removing `delete` in 
favour of `= null`.


Herby


-kg


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


Re: Are frozen Objects faster ?

2013-02-14 Thread Herby Vojčík



Mark S. Miller wrote:




On Thu, Feb 14, 2013 at 10:09 AM, Herby Vojčík he...@mailbox.sk
mailto:he...@mailbox.sk wrote:



Kevin Gadd wrote:

Frozen and sealed objects are both dramatically slower in most JS
engines I've tested. In the ones where they're not dramatically
slower
they are never faster.

The last time I asked on the mozilla and v8 bug trackers I was
informed that there is no plan to optimize for these features
and that
the design of the respective JS engines would make such
optimizations
difficult anyway.

(I find this extremely unfortunate.)


I, on the other hand, find it fortunate. Otherwise, some people
would prematurely freeze objects to gain speed. It would be same
deldisaster/del akwardness as v8 did with removing `delete` in
favour of `= null`.


What are you referring to? What 'delete' was removed?


I meant de facto. People wanting to remove property bar from foo do 
not write `delete foo.bar` anymore; they (at least some significant 
subset) have learned to write `foo.bar = null;` or `foo.bar = 
undefined;`. The reason is perf - `delete` deoptimized hidden classes.



Herby

-kg

--
 Cheers,
 --MarkM

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


Re: Are frozen Objects faster ?

2013-02-14 Thread Herby Vojčík



Andreas Rossberg wrote:

On 14 February 2013 19:26, Herby Vojčíkhe...@mailbox.sk  wrote:

I meant de facto. People wanting to remove property bar from foo do not
write `delete foo.bar` anymore; they (at least some significant subset) have
learned to write `foo.bar = null;` or `foo.bar = undefined;`. The reason is
perf - `delete` deoptimized hidden classes.


And with ES6, those people will hopefully realise that for those
cases, using a Map is a cleaner alternative anyway.


No, it is another scenario. If an object is used as a Map, it should 
degrade to HashMap, it's ok.


The problem is proliferation of `foo.bar = null` in normal code, where 
sometimes you want to remove some property (maybe it was an expando, or 
it is realy not needed any more in the actual phases of the lifecycle). 
In such cases, doing `delete` would degrade your optimized instance into 
a Hash. Thus, people do `foo.bar = null` even if what they want to do is 
`delete foo.bar`.



/Andreas


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


Re: Array subclassing, .map and iterables (Re: Jan 30 TC39 Meeting Notes)

2013-02-12 Thread Herby Vojčík



Rick Waldron wrote:



On Monday, February 11, 2013, Nathan Wall wrote:

Thank you for this explanation.  This is very interesting!  If you
don't mind, I have some questions/concerns I'd like to clear up.
  (In particular I want to make sure I understand; I don't intend to
argue for one side or the other ATM, but this change may require me
to refactor some old code to be future-ready).

Allen Wirfs-Brock wrote:
  The choice we agreed to, at the meeting is
 
  1) Array.prototype.map produces the same kind of array that it
was applied to, so:
 
  for the above example
  m instance of V will be true.
  intArray.map(v=v.toSring()) produces an Int32Array. The strings
produced by the map function get converted back to numbers.

Sounds cool! Does it work?

I rely on the genericness of Array methods quite a lot. For example,
it's fairly common for me to write something like the following:

 var map = Function.prototype.call.bind(Array.prototype.map),
 select = document.querySelectorAll.bind(document);

 var ids = map(select('div'), function(el) { return el.id
http://el.id; });

Currently this would get me an array of string ids for every div on
a page. In a future ES6 with a future DOM where NodeList extends
Array, will `ids` no longer hold an array of strings but try to
remain a NodeList?

There's a good chance this will break some of my code. I'm capable
of changing my code and writing this to be more future-friendly from
now on (I'm not one who prefers backwards compatibility over a
better language). But I would have always assumed I was doing things
correctly before, and I'm curious if the rest of the internet will
be okay..?


Since you're using Array.prototype.map there, your code will indeed give
you an array of string IDs, as it always did.


No it won't. In the current proposal (which I'd like to change, I think 
Array is better default container for map), if NodeList would subclass 
Array, applying (generic) Array.prototype.map on instance of NodeList 
would create a new NodeList and would try to put ids on there.


Herby


Rick


Nathan

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


Re: Array subclassing, .map and iterables (Re: Jan 30 TC39 Meeting Notes)

2013-02-11 Thread Herby Vojčík



Allen Wirfs-Brock wrote:


On Feb 10, 2013, at 3:40 AM, Herby Vojčík wrote:

But I still think it is simpler to specify .map returning array,
always. You know you get an Array, you don't have to worry about magic
of Set, Map etc., if you wish to have it in other kind of container,
use Container.from(...).



But wouldn't you want:
var my16bitVector = Uint16Array.from([1,2,3,4,5,6]);
...
var y = my16bitVector.map(v=v+1)

someExternalAPI(y);

to create a Uint16Array for y? It seems like the most common use cases
want to produce the same kind of elements. Mapping to a different or
broader kind of element is also common, but I think less common. So it's
the case that should take to more to express.


Well, here's the difference. Nearly every kind of .map use I remember 
(or `collect:` in Smalltalk, maybe I should not mix them but they are 
mixed in my mind) are transformation of the object: map objects to only 
some specific property, wrap collection of primitives to objects that 
are created from them, etc. I honestly can't remember any use of .map 
concept that preserves element types beyond educatory `(1 to: 10) 
collect: [ :x | x*x ]`.


That is, my conviction is, .map is mainly used for bigger 
transformations of its elements (I think your v=v+1 example much more 
often happens in-place, that is, forEach; map use-case seems rare for me).



Allen


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


Re: thoughts on ES6+ direction + modules

2013-02-11 Thread Herby Vojčík

I wish you hadn't posted this, it implies something that's not true and
reads as incredibly disrespectful. All input, from all sources, is given
a fair consideration. It stands to reason that well articulated,

From my experience, this is not true.
You can of course argue on what definitions of a fair consideration 
and thoughtful and well researched are.



thoughtful and well researched input is given more consideration—a fact
that's backed by irrefutable, publicly documented evidence.

Rick


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


Re: Array subclassing, .map and iterables (Re: Jan 30 TC39 Meeting Notes)

2013-02-10 Thread Herby Vojčík



Allen Wirfs-Brock wrote:

On Feb 9, 2013, at 3:01 PM, Herby Vojčík wrote:


Allen Wirfs-Brock wrote:

ethods.

The choice we agreed to, at the meeting is

1) Array.prototype.map produces the same kind of array that it
was applied to, so:

for the above example m instance of V will be true.
intArray.map(v=v.toSring()) produces an Int32Array.  The
strings produced by the map function get converted back to
numbers.

2) If you want to map the elements of an array to different kind
of array useArrayClass.from with  a map function as the second
parameter:

var strArray = Array.from(intArray, v=v.toString());

This seemed like a less invasive change then adding additional
target kind parameters to Array.prototype.map.  Also it seems
like a very clear way for programmers to state their intent.

You chose one default, but I think it was not the simplest one. It
is good to see that map is often transforming types, so the same
type may not be the best default (filter is another story).

I think the best would be (it is dead simple): - to _always_ use
Array in map result


In your previous post you said:


1. .map should work for Array subclasses, preserving class



are you changing that position?


That's probably not me who said it :-)


Also, there is another subtlety that is on slide 25 of the deck I
present.  Existing ES6 code may create objects that inherit from
Array.prototype. When running on an ES6 implementation uses of
Array.prototype.map (etc.) in such code can't change their behavior.


I am not TC39 member, so I did not see that slide, but if you say .map 
always produces Array, it does not change the behaviour.


Could you elaborate more, please?


So, the selection of the result class can't be based solely on the
[[Prototype]]  inheritance chain.



- to leave Array.from (as well as Map.from, V.from etc.) as is,
generator comprehension does the mapping for you if you wish one.

So, the examples would be

V.from(x for x in new V); // you say you want the results in V

I don't understand?  This produces the same result as new V; but with
an extra V allocation, creation of a generator, etc.


It was rewrite of Claus' example you were discussing about:

  class V extends Array { ... }
  m = (new V()).map(val = val);
  console.log( m instanceof V ); // false


Another issue, is that some array-like classes instances must have
their size fixed at allocation. This is the case for all the
TypedArrays.  For iterators automatically derived from most arrays,
we can make the size information available.  But for a generator,
there is no way to know how many iterations it will make without
actually running it.   For specification purposes, we may specify the


Hm. Yes, this is problem, then.


from method as accumulating the element values into a List,
allocatininge most TypedArray uses) that the double copy can be
optimized away.  That means that in the usual case the size must be
available at the beginning which precludes using a generator
expression as the usual case pattern.


Yes, then the second point is not-starter.

But I still think it is simpler to specify .map returning array, 
always. You know you get an Array, you don't have to worry about magic 
of Set, Map etc., if you wish to have it in other kind of container, use 
Container.from(...).


Of course, I don't know what that slide 25 was about, but for now I 
argue map is different from concat, filter etc. do not transform 
contents, just manipulate containers.



Allen


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


Re: Jan 29 TC39 Meeting Notes

2013-02-09 Thread Herby Vojčík



Rick Waldron wrote:

# January 29 2013 Meeting Notes

* @@create is a well known symbol that when used as a property of  a
constructor provides the alloca1on method for that constructor.
* New definition of the ordinary [[Construct]] :
   1. Let creator be [[Get]] of this constructors @@create property
   2.  If creator is not undefined, then
   a. Let obj be the result of calling creator with this constructor as
its this value.
   3.  Else, fallback implementation
   a. Let obj be a new ordinary object with its [[Prototype]]
initialized from this constructor's “prototype” property.
   4. Call this constructor with obj as the this value and the original
argument list.
   5.  Return obj.

BE, EA, YK, WH, others: Get rid of the fallback implementation and just
throw if there is no @@create. It's unnecessary complexity.

* Most constructors just inherit Function.prototype[@@create]  which
allocates a new ordinary object with its [[Prototype]]  initialized from
this.prototype (the constructor’s “prototype”  property).
* `new Foo() = Foo.call(Foo[@@create]())`

There are ...args, so this is in fact
  `new Foo(...args) = Foo.call(Foo[@@create](), ...args)`

I would argue this is wrong semantic, it should be
  `new Foo(...args) = Foo[@@create]().constructor(...args)`

At least for builtins are classes, this is attainable. For userland 
contructor functions, this would break, so they probably need the old 
semantics; but there is yet another possibility, I'll show it below[1].



**Conclusion/Resolution**
Consensus on @@create, allocation and initialization decoupling.


Let us assume we want to simulate classic class-based OOP semantics.
There are three roles here, they should be explicitly declared to the 
members of the show:

 * Class identity: this is one that
   * holds statics
   * is used in `new Foo`
   * is used in `extends Foo`
   This is currently played by the function Foo, with [[Construct]].
   Note: deliberately missing [[Call]]ability. It is not really needed.
 More[2] below.
 * Allocator of new instance
   Makes the new uninitalized instance, with necessary magic.
   This is now played by Foo[@@create].
 * Initializer of an instance: this is one that
   * initializes new instance of Foo in `new Foo`
   * initializes new instance of SubFoo
 in `super(...args)` in `new SubFoo`.
   (do someone really think these are separate? I think they are the same)
   This is schizophrenic now. Sometimes, this is played by function Foo,
 sometimes this is played by (potetially different or nonexisting)
 `Foo.prototype.constructor`.

Plus, there is fourth thing/role: knowledge own class. An instance wants 
to know its class (as it Class identity described above), to have 
access to its own statics (dynamically) and ability to use `new`.


This is much like smalltalk's `#class`.

It is now played by `constructor`, but very poorly, since it is often 
missing because of rewriting `.prototype`.


All of these four thing are needed; and third is schizophrenic and 
fourth is missing.


I think the object model regarding `new` etc. should be reformed a bit 
more (@@create was great first step).


By my suggestion of
  `new Foo(...args) = Foo[@@create]().constructor(...args)`
I tried to solve the schizophreny of the third one. If this could be 
attained, the third role could _always_ be played by 
`Foo.prototype.constructor`.


To solve the fourth, I would propose (at least a though experiment) in 
which it is an invariant that (new Foo).constructor === Foo`, that is, 
`constructor` always points to the creator class in case of instances 
created via `new`.


For `class`es (and builtins) this can be achieved easily: write-protect 
`Foo.prototype` (it is in case of `class` and I would presume it is for 
builtins, as well) and write-protect `Foo.prototype.constructor` as well.


For free userland constructor functions, this is more of a problem. 
They can have their .prototype rewritten, and / or .constructor with 
their .prototype. Now I propose the little breaking change (I would like 
to hear how much breaking it is, if you have the opinion, or even data): 
legacy constructor functions will have not only .prototype create, but 
also [@@behaviour] object behind the scenes where:
 * `Foo[@@behaviour].__proto__ === Foo.prototype` (whenever the 
Foo.prototype is changed, new [@@behaviour] should be recreated)
 * default Foo[@@create] would set __proto__ of new instance to 
[@@behaviour], not to .prototype.

 * [@@behaviour] will have write-protected .constructor pointing to `Foo`

An obvious optimization which saves a lot of unnecessary allocation is: 
only create [@@behaviour] lazily when first `new Foo` actually happens 
(majority of constructor function never really [[Construct]]).


(For classes and builtins, let's say [@@behaviuor] will always return 
.prototype)


What this means, (new Foo).constructor is always Foo. The question is: 
is this too breaking? Is there a code that changes .constructor 

Re: Array subclassing, .map and iterables (Re: Jan 30 TC39 Meeting Notes)

2013-02-09 Thread Herby Vojčík



Allen Wirfs-Brock wrote:

On Feb 9, 2013, at 2:16 AM, Claus Reinke wrote:


I am trying to understand the discussion and resolution of 'The
Array Subclassing Kind Issue'. The issue (though not its
solution) seemed simple enough

class V extends Array { ... } m = (new V()).map(val =  val);
console.log( m instanceof V ); // false :(

and I was expecting solutions somewhere along this path:

1. .map should work for Array subclasses, preserving class

2. .map is independent of Array and its subclasses, there are lots
of types for which it makes sense (Sets, EventEmitters, ..)

3. there should be an interface Mapable, implemented by Array and
its subclasses, but also by other relevant classes, such that


the issue is that a map function can broaden the domain of array
elements.  For example,

var intArray = new Int32Array([42,85,127649,32768]); //create a typed
array from a regular array var strArray =
intArray.map(v=v.toString());

If intArray.map() produces a new intArray then the above map function
is invalid.  If intArray.map() produces an Array instance then you
intArray.map instance of intArray.constructor desire won't hold.  We
can't have it both ways without provide some additional mechanism
that probably involves additional parameters to some methods or new
methods.

The choice we agreed to, at the meeting is

1) Array.prototype.map produces the same kind of array that it was
applied to, so:

for the above example m instance of V will be true.
intArray.map(v=v.toSring()) produces an Int32Array.  The strings
produced by the map function get converted back to numbers.

2) If you want to map the elements of an array to different kind of
array useArrayClass.from with  a map function as the second
parameter:

var strArray = Array.from(intArray, v=v.toString());

This seemed like a less invasive change then adding additional target
kind parameters to Array.prototype.map.  Also it seems like a very
clear way for programmers to state their intent.


You chose one default, but I think it was not the simplest one.
It is good to see that map is often transforming types, so the same 
type may not be the best default (filter is another story).


I think the best would be (it is dead simple):
 - to _always_ use Array in map result
 - to leave Array.from (as well as Map.from, V.from etc.) as is,
   generator comprehension does the mapping for you if you wish one.

So, the examples would be

  V.from(x for x in new V); // you say you want the results in V
  intArray.map(v=v.toString()); // collect them in default Array

Herby


Allen

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


Re: Private symbols auto-unwrapping proxies (was: Security Demands Simplicity (was: Private Slots))

2013-01-29 Thread Herby Vojčík



Brandon Benvie wrote:

To elaborate, I've realized that my main disagreement with your position
(really my care at all with the private discussion) is much better
solved by introducing [[CallProperty]]. That is: Proxies currently


... and complicates object model. My main problem with [[CallProperty]] 
is the discrepancy between [[Get]] (used in [[Get]]+[[Call]]) and 
[[CallProperty]] (my assumption that by [[CallProperty]] you mean 
operation that replaces [[Get]]+[[Call]]).


I'd solve it otherwise. Let's say that foo.bar(baz) is split to _three_ 
operations: [[Get]]+[[OopBind]]+[[Call]], where [[OopBind]] resolves 
this. Then, proxies should only be able to trap [[OopBind]] (but it will 
still be the same combination, involving trappable [[Get]] at the 
beginning and ending with (direct) [[Call]]).



handle |this| binding of method calls very poorly. I'm all for either
removing private or making it *really* private, but Proxies are
basically worthless in the private middleground which causes them to
break half the time in ES6 code. But [[CallProperty]] fixes the issue in
a way that seems acceptable to all parties.


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


Re: Adding [[Invoke]] to address issues with methods called on Proxies

2013-01-29 Thread Herby Vojčík



Brandon Benvie wrote:

Responding in this thread since it's a more appropriate place.

1.) It complicates the object model, in that it adds a new internal
method to objects, but it also clarifies it. It falls under the same
category as [[GetP]] and [[SetP]]: they complicate the object model, but
they also clarify it and they are only observable to Proxies. All three
are only observable to Proxies. Proxies are the thing that ultimately
complicates the object model and these are fallout from it, but most of
us agree that Proxies are worth it.


Again, why add something that is only observable to Proxies? It is an 
exception, and it bring much more complication than straight rule. Such 
an exception is future-unfriendly.


And I do not agree that it clarifies the object model. On the contrary. 
It makes it inconsistent.


  var quux = foo.bar;
  quux.call(foo, baz);

was always equivalent of foo.bar(baz). Now, it is not.

[[CallProperty]] is bad because it is alternative to [[Get]], in certain 
situations. What is the problem with, instead, doing it (imo) more 
properly, by reifying [[ChooseThis]](receiver, property) or something 
similar? This will not break the above equivalence, since it will be 
present in all oop calls and inside .apply and .call as well.



2.) The abstract method Invoke already exists in the spec. This is a
thing that the ES6 spec, with its deferring to prototypal inheritance
for some things previously limited to internal properties, needs. Adding
[[CallProperty]] would probably be a near net-zero change (perhaps a
net-reduction) in total spec complexity, since Invoke already exists in
the spec and is largely subsumed by [[CallProperty]].


Special case adds more complexity than extract (imo).
Spec efficiency does not beat complicating semantics.


On Tue, Jan 29, 2013 at 12:56 PM, Herby Vojčík he...@mailbox.sk
mailto:he...@mailbox.sk wrote:



Brandon Benvie wrote:

To elaborate, I've realized that my main disagreement with your
position
(really my care at all with the private discussion) is much better
solved by introducing [[CallProperty]]. That is: Proxies currently


... and complicates object model. My main problem with
[[CallProperty]] is the discrepancy between [[Get]] (used in
[[Get]]+[[Call]]) and [[CallProperty]] (my assumption that by
[[CallProperty]] you mean operation that replaces [[Get]]+[[Call]]).

I'd solve it otherwise. Let's say that foo.bar(baz) is split to
_three_ operations: [[Get]]+[[OopBind]]+[[Call]], where [[OopBind]]
resolves this. Then, proxies should only be able to trap [[OopBind]]
(but it will still be the same combination, involving trappable
[[Get]] at the beginning and ending with (direct) [[Call]]).


handle |this| binding of method calls very poorly. I'm all for
either
removing private or making it *really* private, but Proxies are
basically worthless in the private middleground which causes them to
break half the time in ES6 code. But [[CallProperty]] fixes the
issue in
a way that seems acceptable to all parties.


Herby

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


Re: Adding [[Invoke]] to address issues with methods called on Proxies

2013-01-29 Thread Herby Vojčík



Mark S. Miller wrote:

On Tue, Jan 29, 2013 at 10:52 AM, Herby Vojčík he...@mailbox.sk
mailto:he...@mailbox.sk wrote:



Brandon Benvie wrote:

Responding in this thread since it's a more appropriate place.

1.) It complicates the object model, in that it adds a new internal
method to objects, but it also clarifies it. It falls under the same
category as [[GetP]] and [[SetP]]: they complicate the object
model, but
they also clarify it and they are only observable to Proxies.
All three
are only observable to Proxies. Proxies are the thing that
ultimately
complicates the object model and these are fallout from it, but
most of
us agree that Proxies are worth it.


Again, why add something that is only observable to Proxies? It is
an exception, and it bring much more complication than straight
rule. Such an exception is future-unfriendly.

And I do not agree that it clarifies the object model. On the
contrary. It makes it inconsistent.

   var quux = foo.bar;
   quux.call(foo, baz);

was always equivalent of foo.bar(baz). Now, it is not.

[[CallProperty]] is bad because it is alternative to [[Get]], in
certain situations. What is the problem with, instead, doing it
(imo) more properly, by reifying [[ChooseThis]](receiver, property)
or something similar?


Hi Herby,

Perhaps I missed it, but could you expand on the [[ChooseThis]] idea? Or
provide a link to an earlier discussion if it's already adequately
covered? Thanks.


I replied it in another thread, but it was only on post, and it is 
included here as well (I just called in [[OopBind]] but it was more or 
less just [[ChooseThis]]):


[snip]


 ... and complicates object model. My main problem with
 [[CallProperty]] is the discrepancy between [[Get]] (used in
 [[Get]]+[[Call]]) and [[CallProperty]] (my assumption that by
 [[CallProperty]] you mean operation that replaces
[[Get]]+[[Call]]).

 I'd solve it otherwise. Let's say that foo.bar(baz) is split to
 _three_ operations: [[Get]]+[[OopBind]]+[[Call]], where
[[OopBind]]
 resolves this. Then, proxies should only be able to trap
[[OopBind]]
 (but it will still be the same combination, involving trappable
 [[Get]] at the beginning and ending with (direct) [[Call]]).


[snip]

It is basically the idea that OOP call is three-part:
  [[Get]] (trappable)
  [[ChooseThis]] (by default choosing the base of Ref; trappable)
  [[Call]] (in this context (receiver being proxy) untrappable; if a 
function itself is proxy, it's already someone else's problem)


.apply and .call would do the last two.

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


Re: Adding [[Invoke]] to address issues with methods called on Proxies

2013-01-29 Thread Herby Vojčík

[snip]

It is basically the idea that OOP call is three-part:
[[Get]] (trappable)
[[ChooseThis]] (by default choosing the base of Ref; trappable)
[[Call]] (in this context (receiver being proxy) untrappable; if a
function itself is proxy, it's already someone else's problem)

.apply and .call would do the last two.


I now see that things are more complicated and that it is not as simple 
as it looked. Proxies want to choose what this to use not based on 
function itself, but based on property, I presume, so [[ChooseThis]] 
would need property. But it then doesn't help the


  var quux = foo.bar;
  quux.call(foo, baz);

case, since quux.call have no information that the property was 'bar' 
:-( Pity.


This slightly lowers usability of this solution (one can use 
[[MethodName]] as a property is .call and .apply, but ... that's not 
nice). I think it is still better than [[CallProperty]] that races with 
[[Get]] and is specific for proxies and method invocation case, but.


Or is so that certain kind of proxies would always use own identity and 
another kind always target identity, not based on which property am I 
calling? In that case, this solution is fine.



Herby

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


Re: WeakMap.prototype.clear performance

2013-01-23 Thread Herby Vojčík



Allen Wirfs-Brock wrote:

On Jan 22, 2013, at 4:00 PM, Mark S. Miller wrote:


Should Symbols (whether unique or private) also have a .clear
method, in order to delete all properties named by that symbol?


Of course not.  A Symbol is basically a simple immutable value
disguised as an object.  The is no interesting abstraction layer that


But there is a case for this. Very similar to your cache flushing, I 
admit. Call it unmarking, for example. Symbols (not only private ones) 
are used to monkey-patch object with some alternative-layer of 
properties, which some side-process uses. This side-process may use it 
only for some time, afterwards it may want to just clean after itself. 
This is exactly where I want `symbols.clear()`.


Yes, you can say it used bad tool and should have used WeakMap instead...

Herby


to communicate across. A more appropriate question might be should
there be an Object.deleteAll(obj) function that tries to delete all
own properties on an object.  As far as I know there is no usage
experience that suggests that this is  needed  In contrast, there is
plenty of experience that suggests that flushing a cache is a
common operations and building caches is certainly a use case for
WeakMap.

Allen




On Tue, Jan 22, 2013 at 3:36 PM, Allen Wirfs-Brock
al...@wirfs-brock.com  wrote:

On Jan 22, 2013, at 2:35 PM, David Bruant wrote:


So, to find out if a weakmap is dead, it has to come from
another source than the mark-and-sweep algorithm (since it
losts its precision)... Given the additional prohibitive cost
weakmaps seem to have on the GC, maybe things that would
otherwise be considered too costly could make sense to be
applied specifically to WeakMaps. For instance, would the cost
of reference-counting only weakmaps be worth the benefit from
knowing early that the weakmap is dead? (I have no idea how
much each costs, so it's hard for me to compare the costs) For
WeakMapWithClear, reference counting would declare the weakmap
dead as soon as the new weakmap is assigned to the private
property so that's good. It wouldn't work if some weakmaps are
part of a cycle of course... but maybe that it's such an edge
case that it's acceptable to ask users doing that to break
their weakmaps cycle manually if they don't want the GC not to
be too mad at them.


You know, as much as Jason and I enjoy talking about garbage
collectors, this probably isn't the place to revisit the last 40
years of a highly developed area of specialized CS technology.

We can understand the value of providing a clear method without
talking about GC at all.  Map and WeakMap are examples of object
abstractions that encapsulate a probably complex implementation
level data structure.  As ES programmers we aren't allowed to
know very much about the specifics of those data structures other
than that the spec. says they must provide average access times
that are sublinear with respect to the number of entries in the
collection.  The implementation is probably some sort of hash
table, but it could be based upon b-trees or some other
appropriate data structure.  An implementation might even
dynamically change data structures and algorithms as elements are
added or removed.

Regardless, as ES programmers that is all forbidden knowledge.
All we  can know and express are things that are exposed through
the abstraction's API. An operation like clear, even those it
might be possible to achieve the same abstract end result using
other operators like delete, allows us to express an intent that
tunnels through the abstraction boundary.  For a large number of
elements, it is quiet likely that the underlying data structure
can be cleared or reset to no entries far more efficiently than
performing an sequence of isolated deletes for the total number
of elements.  But if the clear method does it exist we can't
express that intent and hence the optimization is impossible.

Allen

-- Cheers, --MarkM

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


Re: Private symbols as WeakMap sugar

2013-01-17 Thread Herby Vojčík



Brendan Eich wrote:

David Bruant wrote:

Hi,

This is an idea naturally derived of all the current discussions about
WeakMaps and Private symbols. The proposal is easily summarized by
these lines of code:

var wm = new WeakMap();
var o = {};
o[wm] = 12 // desugars to wm.set(o, 12)
var a = o[wm]; // desugars to wm.get(o);
wm in o // desugars to wm.has(o);
delete o[wm] // desugars to wm.delete(o);


You are not showing the desugaring in general:

function get(o,x) {
return o[x];
}

must transform to

function get(o,x) {
return (x is WeakMap) ? x.get(o) : o[x];
}


I'd go for genericity here:
  function get(o,x) {
return x.@@isReversedPseudoProperty ? x[o] : o[x];
  }

combined with OMR which gives WeakMap x[o] ability, it could be generic 
and allow other reversed getters.



This is not an acceptable hit for every []-named property access.

/be


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


Re: Security Demands Simplicity (was: Private Slots)

2013-01-17 Thread Herby Vojčík



Mark S. Miller wrote:

I also agree with David that unique symbols are not an encapsulation
mechanism, but rather, merely a mechanism to avoid namespace
collisions.

However, after the Private Slots thread, I spent a sleepless night
chewing on getting rid of private symbols. I now think we should.
Going back to my earlier


On Wed, Jan 16, 2013 at 12:37 PM, Mark S. Millererig...@google.com  wrote:

My position on private symbols.

My position on classes is and has always been that classes are worth
introducing into the language *only* if they give us, or can be used
with, an affordable means for true object encapsulation. Assuming
Allen is right about what actual implementors will do (which I find
plausible) then WeakMaps are not that means.


I still have this position on classes. But I no longer buy that
pessimistic conclusion about WeakMaps. Consider how WeakMaps would be
used by the expansion of classes-with-private. Just 'cause it's on the
top of my head, below I use the old representation of one WeakMap per
class providing access to a record of all the private state. For the
same reason, I'll use the encapsulation of the Purse example without
any of the numeric checks.

class Purse { ... an example w/o and w/ external WeakMap

Thus, no matter what the spec says, normatively or not, about expected
storage costs, competitive pressures will drive JS engine implementors
to make this efficient. The way to make this efficient is by the
technique previously discussed -- hang the private state off of the
object, not the weakmap. Use the weakmap only as an unforgeable token
for naming and accessing this state. If we get rid of private symbols,
we should expect this pattern of usage of WeakMap to have the same
cost that private symbols would have had. We can help implementors
achieve that by having this expansion call instead
WeakMap(USE_KEY_LIFETIME_HINT) or whatever it is called. Then
implementations would not have to recognize the pattern by other
means.

Complexity is the enemy of security. We already have four
encapsulation mechanisms in ES6 in addition to private symbols:
1) functions encapsulating lexical variables
2) WeakMaps
3) proxies encapsulating handlers and targets
4) modules encapsulating what they don't export.

With enough spec and engineering effort, any of these could be grown
into a means for providing efficient class/object encapsulation. Of
them, I think #2 is most plausible. Even is we find #2 does not work
out, we should think about growing one of the other candidates as an
alternative to private symbols. Security demands simplicity, and
semantic simplicity is more important than implementation simplicity.



This leads me to the question: Are symbols needed at all (even unique 
ones)? They could be implemented using WeakMap (or any other external 
encapsulator) as well. The only difference is, they would be known and 
reflectanle.


Thus (including my idea in Private symbols as WeakMap sugar), if we 
could write


  obj[prop]

and mean

  [[isExternalEncapsulator]](prop) ? prop.get(obj) : legacy obj[prop]

then WeakMaps will simply have @@isExternalEncapsulator return true.

The reflectability is the only other matter to be solved. In case of 
symbols, API like gOPN and Object.keys() was not touched, and other API 
must have been added to include symbols.


So, thinking about it, if there were no symbols at all but there were 
(more generic) encapsulators, one can simply add APIs to return visible 
encapsulators, the same as it return symbols now (the encapsulators need 
to know if they are reflectable or not, of course).


I think there may be less confusion because encapsulators would clearly 
be different beasts than properties; symbols tried to be as similar as 
possible but even then they need different API.



--
 Cheers,
 --MarkM


Herby

P.S.: Now that I think about it, encapsulators need to be weak, so they 
do not keep an instance living; therefore probably only WeakMaps are 
legible to be one.


So alternative proposal is to allow obj[wm] and to allow wm to set 
itself and reflectable/nonreflectable when used in obj[wm]. Thus, wms 
can replace symbols altogether.


P.P.S.: Or not (reacting to only WeakMaps are legible). It can be done 
other way: all the external encapsulator are weak by default (in a 
sense, their pointer to instance is not treated as strong). Probably 
just a crazy thought experiment... but in that way, one need no WeakMap, 
just a Map used as external encapsulator to have weak Map ;-)

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


Re: unknownPrivateSymbol trap (was: WeakMap better than Private Symbols? (was: direct_proxies problem))

2013-01-15 Thread Herby Vojčík



Tom Van Cutsem wrote:

2013/1/15 David Bruant bruan...@gmail.com mailto:bruan...@gmail.com

Le 15/01/2013 20:32, Tom Van Cutsem a écrit :

As far as I recall, the purpose of the trap was to allow a
membrane or revocable proxy to explicitly abort accesses involving
such private symbols. The point being that if a membrane can't
abort such accesses, then collaborators on both sides of the
membrane could circumvent the membrane by communicating via a
previously agreed upon private symbol.

Yes, we've discussed that in length with Nathan Wall :-)


Sorry, I only now catched up with that. I don't have anything more to
add to that discussion.

So in conclusion:
- we still need unknownPrivateSymbol


Is it needed? Maybe the fail/forward decision canbe set beforehand, 
when creating the proxy. Then, no trap will be called (but you cannot 
change the response in time; OTOH, is there a use case for it?).


Or does it do something more sophisticated then just telling forward 
or fail for situation that I am accessing some unknown private symbol?



- a return/throw protocol may be more suitable than a boolean return
value for this trap

Cheers,
Tom


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


Re: WeakMap better than Private Symbols? (was: direct_proxies problem)

2013-01-10 Thread Herby Vojčík



Nathan Wall wrote:

 // ES6 Symbols

 // Forgive me for not knowing what the current
 // correct syntax is for creating a symbol:
 let timestamp = new Symbol();

 class SimpleDate {

 construct(time) {
 this.setTime(time);
 }

 setTime(time) {
 this[timestamp] = +time;
 }

 getTime() {
 return this[timestamp];
 }

 }


 // ES6 WeakMap

 let timeMap = new WeakMap(),
 // Store WeakMap methods to maintain integrity of the internal state.
 WeakMapGet = Function.prototype.call.bind(WeakMap.prototype.get),
 WeakMapSet = Function.prototype.call.bind(WeakMap.prototype.set);

 class SimpleDate {

 construct(time) {
 this.setTime(time);
 }

 setTime(time) {
 WeakMapSet(timeMap, this, +time);
 }

 getTime() {
 return WeakMapGet(timeMap, this);
 }

 }

AFAIK the two ES6 implementations above should function the same, except when 
(1) a Proxy uses a SimpleDate as the target and (2) a SimpleDate is frozen.

In the case of (1), the implementation using a private symbol will have 
internal accesses to the `timestamp` symbol exposed through the 
unknownPrivateSymbol trap.

In the case of (2), the implementation using a private symbol will fail on a 
call to `setTime` when the object is frozen (I think).


IIRC, private symbols are exempt from freezing.

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


Re: Good-bye constructor functions?

2013-01-09 Thread Herby Vojčík

Sorry if I was too dense in my reply so things weren't understood. I
don't know how to reply put things efficiently because without big
picture, isolated cherry-picks seem ridiculous and properly put big
picture is often tl;dr-ed.

Concrete replies below.

Allen Wirfs-Brock wrote:

On Jan 8, 2013, at 12:45 AM, Herby Vojčík wrote:



Allen Wirfs-Brock wrote:

On Jan 7, 2013, at 4:09 PM, Herby Vojčík wrote:


...

I just don't see such an inconsistency in the current ES6 spec.
draft. A constructor is just a function that is usually called
with a this value. This is true whether it is called by the
[[Constructor]] internal method or via a super/super.constructor
call. In either case, the primary purpose of the constructor is
to perform initialization actions upon the this value. Where is
the inconsistency?

(I claim that) in any circumstances, what developers want to
express when writing `super(...args)` in the constructoro of
SubFoo, is: On my this, which is now instance of SubFoo, I want
the identical initialization code to be run, which `new
Foo(...args)` would run to initialize newly created instance of
Foo

That's not true. Because the spec is trying to serve two masters:
F and F.prototype.constructor. It is impossible.

The fixed semantics of [[Construct]] for `class` ((1) above)  is
fixing this by only serving one master: F.prototype.constructor
(in line 3).


I agree with your above statement about initialization.  But I also
content that is exactly what the current specification of super does
within a constructor function (subject, of course to what the
invoked methods actually are coded to do).  What I don't see  is why
you


What's it? super does call the .prototype.constructor of superclass,
yes, I know that well, ...

think otherwise.  I need a clearer concrete explanation of what you
see is the problem, prefably without a forward reference to what you
think is the solution.

...but new does not call the .prototype.constructor.

There this does not hold for `super(...args)` behaviour:
On my this, which is now instance of SubFoo, I want the identical
initialization code to be run, which `new Foo(...args)` would run to
initialize newly created instance of Foo.

And if you argue they are identical at the beginning, I say they can be
desynchronized, they will, and it does not matter how is the default case.

This state of serving two masters (new F, super F.prototype.constructor)
is a design issue / inconsistency / bug in the core of the language.

And sorry if I mention the aolution (it is simply call
.prototype.constructor in new for `class`), but it saves the model of
super-without-special-cases for constructor, which is fine (special
cases aren't).


The only anomaly I see is that a handful of legacy built-ins do
completely different things for new operator originated calls in
 contrast to regular function calls. There is no confusion in
the spec. about this and the mechanism for accomplishing it.
However such split behavior can't be declaratively defined in a
normal function or class declaration. In the other thread at
https://mail.mozilla.org/pipermail/es-discuss/2013-January/027864.html



I described how this split behavior an be procedurally described

in such declarations and also described how the same technique
can be applied to the offending built-in constructors (r any
user defined class constructor) to discriminate between
initialization and called behavior, even when called via
super.

Yes, but it is a workaround.


Or, alternatively stated, it shows how the objective can be met
without any further complicating the actual language.   That is
arguably a good thing, not just a woprkaround


Taken ad absurdum, JS is turing complete, you can achieve anything
without complicating the actual language.


The only fix I saw that you made to super was that in you
sketch constructor methods defined via a class definition are
only used for instance initialization, so there doesn't need to
be any code to determine between initialization and call
behavior. Constructor behavior is always initialization
behavior.

Yes, it is there. As a free bonus, btw. The main druver for the
design was new/super two masters fixing. Then, later (Brendan Eich
will not like this ;-) ) the beauty of breaking the tight coupling
and not needing [[Call]] at all for object with [[Construct]].

There are in fact TWO freebies: - [[Call]] separated from
[[Construct]] - you get default constructor for free; by not
defining it explicitly.


Sorry, I still don't see it, you have to explain both the problem
and your solution more concretely.


You probably see [[Call]] / [[Construct]] separation - class object's
[[Call]] is orthogonal to what [[Construct]] does, since it is specified
to call .prototype.constructor. It follows naturally from the fact that
class !== constructor.

So the issue needing explanation is free default constructor, I
presume (tell me if I am wrong).

It goes this way: if the [[Construct]] has proposed

Re: Good-bye constructor functions?

2013-01-08 Thread Herby Vojčík



Allen Wirfs-Brock wrote:


On Jan 7, 2013, at 4:09 PM, Herby Vojčík wrote:




Allen Wirfs-Brock wrote:

OK, I ready you proposal. I'll summaries it:

class Sub extends Super {
constructor (...args) {
super(...args); //or super.constructor(...args) because they mean the
same thing.
}
}

creates an (almost) ordinary object that is the initial value of the
Sub binding. The [[Prototype]] of Sub is the value of Super. Sub is
created with a prototype property whose value is a new ordinary
object whose [[Prototype]] values is Super.prototype. Sub.prototype
has a method property named constructor whose value is a super
bound method function with the user specified body. There is nothing
special about this method, it it just like any other method defined
in a class declaration. In particular it does not have a
[[Construct]] internal property.

The only thing exotic about Sub is that the object has a
[[Construct]] internal method. It does not have a [[Call]] internal
method. The definition of its [[Construct]] in almost JS pseudo code is:



(1):

//internal method this.[[Constructor]](argList):
let newObj = this.@@create(); //eg Sub.@@create();
let replacementObj = this.prototype.constructor.apply(newObj, argList);
if (typeof replacementObj == object replacementObj !== null)
return replacementObj
return newObj;

(end of (1))


Implications:
Sub === Sub.prototype.constructor evaluates to false.
To create a new instance of Sub say:
new Sub()
The following is a TypeError, because Sub does not have a [[Call]]
internal method:
Sub()
The following is a TypeError, because Sub.prototype.constructor does
not have a [[Construct]] internal method:
new Sub.prototype.constructor()
Sub.prototype.constructor can be called directly or as a method
invocation including via a super call a subclass of Sub.

It seems to me, all you have accomplished here is to make it illegal
to call a class object directly as a function. If we were starting


From technical PoV*, yes.
Oh, and I fixed the super / new inconsistency.


I just don't see such an inconsistency in the current ES6 spec. draft. A
constructor is just a function that is usually called with a this value.
This is true whether it is called by the [[Constructor]] internal method
or via a super/super.constructor call. In either case, the primary
purpose of the constructor is to perform initialization actions upon the
this value. Where is the inconsistency?


(I claim that) in any circumstances, what developers want to express 
when writing `super(...args)` in the constructoro of SubFoo, is:
  On my this, which is now instance of SubFoo, I want the identical 
initialization code to be run, which `new Foo(...args)` would run to 
initialize newly created instance of Foo


That's not true. Because the spec is trying to serve two masters: F and 
F.prototype.constructor. It is impossible.


The fixed semantics of [[Construct]] for `class` ((1) above)  is fixing 
this by only serving one master: F.prototype.constructor (in line 3).



The only anomaly I see is that a handful of legacy built-ins do
completely different things for new operator originated calls in
contrast to regular function calls. There is no confusion in the spec.
about this and the mechanism for accomplishing it. However such split
behavior can't be declaratively defined in a normal function or class
declaration. In the other thread at
https://mail.mozilla.org/pipermail/es-discuss/2013-January/027864.html I
described how this split behavior an be procedurally described in such
declarations and also described how the same technique can be applied to
the offending built-in constructors (r any user defined class
constructor) to discriminate between initialization and called
behavior, even when called via super.

Yes, but it is a workaround.

Bonding identity of class with identity of constructor is not a law. It 
was just a workaround to make class without `class`. Nor, ultimately, 
can it be said it is preferred by the crowd (they have little other 
oossibility, it is not a preference but a legacy; similar to assigment 
is user preference over Object.define was not true, because of ES3 
legacy and ES5 being fairly new; I think this is the same pattern).


Physical separation allows it naturally, should one want it. By stopping 
serving F and serving F.prototype.constructor exclusively in new/super.



The only fix I saw that you made to super was that in you sketch
constructor methods defined via a class definition are only used for
instance initialization, so there doesn't need to be any code to
determine between initialization and call behavior. Constructor behavior
is always initialization behavior.


Yes, it is there. As a free bonus, btw. The main druver for the design 
was new/super two masters fixing. Then, later (Brendan Eich will not 
like this ;-) ) the beauty of breaking the tight coupling and not 
needing [[Call]] at all for object with [[Construct]].


There are in fact TWO freebies:
 - [[Call]] separated

Re: Good-bye constructor functions?

2013-01-08 Thread Herby Vojčík



Kevin Smith wrote:

I think it's arguable either way.  I mean, the initializer-only behavior
advocated by Allen et al makes the class useless when called (as opposed
to new'd).

I don't think such an opinionated approach is really necessary.  One can
account for the funky behavior of the built-ins by providing an
additional call hook on the class, and leave everything else as is.
  When the class is called (as opposed to new'd), it would use that hook
instead of the constructor.  (super() would still use the parent's
constructor function.)

It could be supported with syntax like so:

 class C {
 static(...args) { /* call behavior */ }
 }


Read my reply to Allen, it shows more general solution there. In a few 
words, with class and constructor separated, you can specify what object 
should represent the class (and is given appropriate .prototype and 
[[Construct]]), would you want to (otherwise, plain object is created 
for you). One of the options is you can specify that a function should 
represent it:


  class C {
static function(...args) { /* call behaviour */ };
  }

though you can of course put any expression there. Another good 
candudate is {...} object literal.



I think one could also make a case that the default behavior for such a
hook would be to new the class, as some built-ins do (and as many
current JS classes attempt to do):

 class C {
 static(...args) { return new C(...args); }
 }


Yeah, in my proposal there is no default [[Call]] (have no reason for 
general object). But it is more general.



This seems like a pretty clean design to me.

{ Kevin }


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


Wouldn't being bolder on new constructs save the breaking the web costs for future?

2013-01-08 Thread Herby Vojčík

[repost; first version a few days ago disappeared somewhere]

Hello,

recently I came over two issues of the very similar pattern, involving 
semantics of new language constructs. In both cases it seems to be that 
being bolder about changes that _new_constructs_ bring (that is, not 
making too little steps) may save the cost of can't make progress here, 
because it would be breaking change for the web.


(just 7 more paragraphs, pls read on :-) ):

First one was in the thread Good-bye constructor functions? where the 
discussed topic were new construct class and super. As it stands 
now, they are buggy (internally inconsistent), and thinking about 
possible solutions I discovered that with `class` there is little need 
to couple class to its constructor, so I proposed leaving this box and 
open the space of what can be as Foo in `new Foo` to any [[Construct]] 
bearing entity (that is, so that `class` produces plain object with 
[[Construct]] instead of legacy coupling its identity with the identity 
of the constructor).


(let's pretends that we overcome technical details and the proposal may 
actually work; I showed in the post that it may very well be so; I want 
to discuss the higher pattern of defensiveness vs. later compatibility 
problems here)


One reason I brought up why it would be fine to consider now (not later) 
is: if `class`, as a new language construct, behaves same as legacy 
constructor functions (tightly coupling the identity of class and 
constructor), people using ES6 accept that this is how `class` works. 
If later we would want to liberate space of object usable as 
constructor (in `new`), by making `class` return non-coupled class 
objects, it would not be possible because it would break existing code.


OTOH, if `class` would return class object decoupled from constructor, 
it may impose some tax to refactoring existing class-like constructs 
into `class` keyword, but they adopt that space of constructors have 
widened and no backward compatibility problem would appear as with 
splitting it into two steps.


The second one was the reified-nil discussion involving 
pattern-destructuring and existential operator (again let's pretend 
technicalities can be solved). There, the issue was the semantics of 
existential operator (and consequently, refutable destructring, since 
they are coupled) would be simplified by involving nil object into the 
equation; by returning it from existent operator or inside refutable 
destructuring. One possibilty was to include nil object head-on into the 
language (as part of {undefined, null} ==-equivalence group), thus 
making it first-class and make things like `foo = (bar = p?.q).r` work fine.


Another, defensive, possibility is to use nil behind the scenes, but to 
change it to undefined when it becomes visible, with the proposition to 
include first-class nil in ES7. This brings little cost now, but in ES7 
I am afraid of the same effect as in previous case; notably, that there 
already will be code that uses new constructs (refutable destructuring 
or existential operator if included in ES6), but that would be broken if 
ES7 change the semantics to first-class nil. Again, this would not be 
problem if the new constructs bring the new semantics right on.


Am I missing something or is there something about this pattern? That 
new constructs, when being more bolder with its semantics, it can

a) save backward compatibility cost compared to more granular progress;
b) can be used to piggyback new semantics fairly cheaply (since it is a 
new construct in this version so it is more tolareated to bring its new 
semantics with it)?


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


Re: Good-bye constructor functions?

2013-01-08 Thread Herby Vojčík



Brendan Eich wrote:

Herby Vojčík wrote:

In a few words, with class and constructor separated, you can specify
what object should represent the class


Why? Where are the use-cases driving this, which goes beyond class as
constructor function that can be called as well as new'ed?


This question is unfair: no one have use cases for this, when it was 
not possible at all in the language.


I'd ask the contrary*: what are the use case of tying class with its own 
constructor function?


*given the virtual scenario where those two are not tied


(and is given appropriate .prototype and [[Construct]]),


By mutation of the result of an evaluated expression?


Good question.

Well, that static Expr; was the second step, a possible cowpath when 
you allow the cows visit those green pastures beyond class tied to the 
constructor. So don't take it (the static syntax) as true proposal.


But to answer, yes, by modifying it.

In case of {} literal object, it's fine; no problem.
In case of function (...) {...} (or (...) = {}) also no problem: it 
is fresh creation and its [[Construct]] and .prototype may be changed 
accordingly.
In case of any other expression: you've been warned, but if you really 
want, you can (in case you put already existing class-like there, it 
fails, already having non-writable .prototype).



would you want to (otherwise, plain object is created for you).


What use-case?


Green pastures.


One of the options is you can specify that a function should represent
it:

class C {
static function(...args) { /* call behaviour */ };
}

though you can of course put any expression there. Another good
candudate is {...} object literal.


This is innovation beyond any cowpath or stable strawman we've promoted
to Harmony in time for ES6. It goes beyond what we need, which Kevin
pointed out succinctly: per-class @@call specialization.


This static syntax was an example of what can follow.
It was kind-of a carrot. Showing that you can do this separation very 
cleanly, if you have the class and constructor separated.


What I care for now, is the first step - opening the gates for 
[[Construct]] and decoupling it from need of [[Call]]able function.


Or at least the first half-step: the fixed [[Construct]] semantics, that 
fixes super doesn't run the same initialization code as new SuperClass 
would, and paving the way to, possibly, [[Construct]] on different objects.



/be


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


Re: Wouldn't being bolder on new constructs save the breaking the web costs for future?

2013-01-08 Thread Herby Vojčík



Brendan Eich wrote:

You are describing path dependency, which afflicts us all, in various
evolving systems including JS.

We cannot keep resetting ES6 to include and think through and make
consistent things such as nil. Sorry, that trades off badly against
developers' time -- they need the good stuff coming already in top
engines, which Allen is drafting.


If you would explain this better, I'd be glad - it is too dense for me 
to understand (especially include and think thorugh and they need the 
good stuff ...). Thanks.



And since we're only human, along the dependent paths we walk, missteps
happen. If we can back up and take a better path in time for ES6, we will.


I understand there is a legacy, but I am deeply convinced there is 
hardly better path through which fix(es) can be made than through new 
construct. Because old ones must work as expected.



Another thing we try to do: make incremental progress edition by
edition, based on experience (pave the cowpaths, lessons from nearby
languages, championed designs that are prototyped early, e.g. proxies),
but not close important doors. This is called future-proofing.


What are those champions and championed you use in meeting notes 
often? Thanks again. :-|



Your desire to make class object identity !== class constructor function
identity could be viewed as future-proofing, but we have to pick some


Exactly (and with nil as well, though there it is a bit weaker; the 
whole OP was about fixfuture-proof combo).



identity for ES6. And again, apart from the need to separate constructor


some [non-tied] identity I'd say, when the proposal is about making 
those identities separated. That's why I proposed (as a general, first 
step) the most general thing - a plain Object. As a most general one, it 
is most future-proofing.



invocation via () from invocation view new, we don't have strong
motivation to future-proof.


Hm.

What exactly is future-proof? How does it relate to enough space for 
new cowpaths and progress? These things are really mixing in my head, 
probably because they really are somewhat intertwined.


If future-proof is really _only_ about Just don't make this impossible, 
eventually, that is, if it is about preventing unnecessary constraining 
(eg. when existing things are fixed / specced better) a specific known 
use case is probably good enough as a criterion whether to future-proof.


But I think this is not a case for future-proof which is combined with 
additions (not updates). Additions invlove those new spaces for 
cowpaths. There, you cannot (I think) use some specific use case as a 
criterion, because you don't know where and how the cows will walk.


So I wonder if it is more a future-proofing or opening the gates? I am 
saying that class !== constructor proposal is not just a 
future-proofing, it's 'open the gates to use plain objects as classes 
combined with future-proofing any (normal) object can be, eventually, 
used within new / extends, the user chooses.


I'd like to ask my question on the original post again, sorry. If there 
is future-proof combined with new space for cowpath possibility and 
it can be brought in with the new feature, is it not worth considering, 
given that it cannot be done later when new feature will be stuck with 
already given, probably inherited from legacy, semantics?


However I see at it, it more than future-proofing. It is 
future-proofing--model-evolution--only-t6-be-efficiently-done-now.


I was asking on such combos. Or I see it wrongly? I am really deeply 
convinced that once class will produce legacy class===constructor 
pattern, no [[Constructor]] freeing can ever happen because there will 
already be code that uses class and exploits that fact; the same is for 
existential operator not returning nil - later it cannot be switched.



It's easy to wrap up your own designs along neater lines that themselves


Yes.


have lots of dependencies (nil in language is controversial, from my
twitter survey -- it arguably hides errors). Mature language design,


Yes, it hides. :-/


really all successful language design however radical, shies away from
running ahead along one path too far, at least in the main line. That
would be ECMA-262, so ES6 ;-).


Would changing [[Construct]] semantics for `class` (at least half a 
step) to clearly follow .prototype.constructor being a too far ahead 
one path? It gives free new/super consistency and free default 
constructors (and insight into class/constructor separated worldview)?


I don't consider even the real class/constructor separation too far 
ahead, it is little well-placed design change (in a new construct).



/be


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


Re: fail-fast object destructuring (don't add more slop to sloppy mode)

2013-01-08 Thread Herby Vojčík



Brendan Eich wrote:

Herby Vojčík wrote:

We need to detail how Nil works, how it cannot be wrapped or observed,
etc. in order to maintain equivalence.


In my naive view, [[GetP]] returns Nil, [[SetP]] does nothing,
[[Call]] return Nil. But there are sure some nasty details down there.


Yeah, this is unsafe by design, if the spec has a bug then Nil leaks
out. Want undefined in ES6, not Nil.


I don't understand the unsafety. If Nil is observable part of the
language, then this is natural semantics. If it should be hidden,
that's another story.


I assumed from context (cited above) that you were talking about
destructruing in ES6. That spec lacks Nil as an observable and must
censor any internal Nil specification type. Could be done, but I argue
it's safer to leave [[GetP]] etc. dealing in undefined for now.

Of course if we want Nil in the language, then full speed ahead! That
would be later (ES7 or above), if ever.


Well, the objection that reified nil hides errors is valid; it bugged 
me, too. I pondered how it can be solved, or if it will be obstacle big 
enough.


In the light of this I think nil-underneath-resurfaced-as-undefined is 
good strategy, things like

  (foo=o.p?).q
must be augmentede a bit more:
  (foo=o.p?)?.q

I think it is a problem only for existential operator, destructuring has 
no subexpressions.



/be


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


Re: fail-fast object destructuring (don't add more slop to sloppy mode)

2013-01-08 Thread Herby Vojčík



Herby Vojčík wrote:

In the light of this I think nil-underneath-resurfaced-as-undefined is
good strategy, things like
(foo=o.p?).q
must be augmentede a bit more:
(foo=o.p?)?.q


Well, I meant this, the previous example is a bit strange:
(foo=o?.p).q
must be
(foo=o?.p)?.q


Herby

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


Re: Allowing super to use EvaluateConstruct, or How do I inherit from Date?

2013-01-07 Thread Herby Vojčík



Allen Wirfs-Brock wrote:


I think the real issue is whether we want to encourage the style of
constructor where called as a constructor and called as a function
do completely different things. I'm leaning towards the conclusions that
we shouldn't. One reason is that the language is fighting so hard
against that pattern. Anything that requires multiple low level hacks to
the language semantics (and possibly new syntax) to make it just work
probably is something that shouldn't be done.


Well, I would disagree strongly.

The problem here stems from tightky coupling the constructor function 
to the class. Those two things can be very cleanly and minimally 
sepaerated.


Read my Good bye constructor functions? post from Dec 30. This pattern 
(class = constructor) is very deeply grown into thinking of JS 
developer, but it is not the law. It is very easy to get rid of it.


Then, nothing from below is ever needed. It all follows naturally. Anf 
without hacks.



For the non-spec readers out there, here is the jury rigging pattern.
Every class in the spec. that has different constructor/function call
behavior has (will have) a @@create method that allocates its instances
and in the process tags the instance with a brand and perhaps a not yet
initialized flag. In a new expression, the @@create call happens before
the call to the actual constructor function and the result of the
@@create call is what is passed as the this value to the constructor.

The constructor function, itself, is defined to determine its behavior
based upon the this value that is passed to it. It the this value is
branded with the instance brand, the constructor initializes and returns
the instance according to its normal definition. Otherwise, if the this
value is not an object or an object without the instance brand then the
constructor performs the call functionality.

For the existing built-in this jury rig appears to be adequate for
ensuring compatibility with all existing code. Consider all the ways
that, for example, Number can currently be called as a function:

let n;
n = Number(1234); //this is undefined so jury rig takes ToNumber path
within constructor.
n = Number.call(null, 1) //this is null so jury rig takes ToNumber
path within constructor.
n = Number.call(1, 1) //this is not an object so jury rig takes
ToNumber path within constructor.
n = Number.call(new Object, 1); //this is an object without the number
brand so jury rig takes ToNumber path within constructor.
n = {foo: Number}.foo(1); //this is an object without the number brand
so jury rig takes ToNumber path within constructor.
n = Number.call(new Number(2), 1); //this is an object with the
number brand but it is already initialized so (for backwards compat)
jury rig takes ToNumber path within constructor.
Number.prototype.bar = Number;
n=new Number(2).bar(1; //this is an object with the number brand but
it is already initialized so jury rig takes ToNumber path within
constructor.

But in ES6 (now backwards compat issues here):
class MyNumber extends Number {
additionalNumberMethod () {}
}

n = new MyNumber(1); //default constructor does super.constructor call
with new instance created by Number.@@create, so initialization path
taken with Number.

n = MyNumber(1) //default constructor does super.constructor call with
undefined as this value, so ToNumber path taken and Number(1) is returned.
But if MyNumber wants to also expose its own explicit conversions
behavior it will need to provide its own constructor that decides when
to take that path

Here is a ES level example, of defining a class that uses the called
same as new pattern:

const $myBrand = new Symbol(true);
import $create ...;

class MyObj {
constructor () {
if (typeof this !== 'object' || this == null || !Reflect.has($myBrand))
return new MyObj();
/* could check here for this already initialized */
/* do any initialization */
this[$myBrand] = true; //tag as initialized
}
}
Object.mixin(MyObj, {
[$create] () {
let obj = super(); //call default @@create
Object.defineOwnProperty(obj,$myBrand,{value: undefined, writable: true});
return obj;
}
});


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


Re: Good-bye constructor functions?

2013-01-07 Thread Herby Vojčík



Allen Wirfs-Brock wrote:

OK, I ready you proposal.  I'll summaries it:

class Sub extends Super {
constructor (...args) {
super(...args);  //or super.constructor(...args)  because they mean the 
same thing.
   }
}

creates an (almost) ordinary object that is the initial value of the Sub binding.  The 
[[Prototype]] of Sub is the value of Super. Sub is created with a prototype property 
whose value is a new ordinary object whose [[Prototype]] values is Super.prototype.  Sub.prototype 
has a method property named constructor whose value is a super bound method function 
with the user specified body.  There is nothing special about this method, it it just like any 
other method defined in a class declaration.  In particular it does not have a [[Construct]] 
internal property.

The only thing exotic about Sub is that the object has a [[Construct]] internal 
method.  It does not have a [[Call]] internal method.  The definition of its 
[[Construct]] in almost JS pseudo code is:

   //internal method  this.[[Constructor]](argList):
   let newObj = this.@@create();  //eg Sub.@@create();
   let replacementObj = this.prototype.constructor.apply(newObj, argList);
   if (typeof replacementObj == object  replacementObj !== null) return 
replacementObj
   return newObj;

Implications:
Sub === Sub.prototype.constructor evaluates to false.
To create a new instance of Sub say:
new Sub()
The following is a TypeError, because Sub does not have a [[Call]] internal 
method:
   Sub()
The following is a TypeError, because Sub.prototype.constructor does not 
have a [[Construct]] internal method:
new Sub.prototype.constructor()
 Sub.prototype.constructor can be called directly or as a method invocation 
including via a super call a subclass of Sub.

It seems to me, all you have accomplished here is to make it illegal
to call a class object directly as a function. If we were starting


From technical PoV*, yes.
Oh, and I fixed the super / new inconsistency.


over that might be a reasonable design choice. But we have a legacy
to consider. Even if we think we should discourage direct calls to


Ignoring Foo.call(this) replacable by super, mostly, class is used for 
new Foo and for Foo.staticVar. I argued the change is big in its wider 
implication, even scary, maybe (but I see it as in fact minimal), but 
should not (imo) beat legacy much; because the fact of the tight 
coupling was not exploited so much.



class objects (I think I'm now in that camp) actually making it an
error seems like it may be too big of a step away from the legacy
conventions.


And there is no better time to do that step than now, when class is new 
construct in the language.


*There is more than narrow technical PoV.  By returning plain object 
with exotic [[Construct]], working in nearly every detail as a class, 
while affording not to be the constructor itself, you effective say 
openly You can use any [[Construct]]ified object as a class in ES6+. 
Gates are finally open.


It can be blessed by Reflect.makeClass(classObject, protoObject) or 
similar API.


It can bring lots of new patterns and cowpaths into the language.
If people don't want plain object to be the class, but their existing 
object x, they do

  Reflect.makeClass(x, (class {...}).prototype);

and they then can `new x`. They choose what they will use as x for new 
operator; because now class is one object and constructor is another.


For example, the criticized pattern of 'function that does differently 
for [[Call]] and [[Construct]]' could now be created as well. Just 
'makeClass' it.



The main message of this proposal is that beyond fixing super/new 
inconsistency, it opens new world for classes, not restricted by the 
legacy tightly bound class===constructor objects.


And by making class to return this kind of 'decoupled' classes, this 
widened view to who may be used as a class in new / extends? is 
effectively blessed.


You cannot open it later. Because there will be lagacy code that already 
uses `class`.


(I'd stress again, that, imo, that change is very little, too little for 
the fruits it can bear. Fix me if it breaks something critical)



Allen


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


Re: Good-bye constructor functions?

2013-01-07 Thread Herby Vojčík



Herby Vojčík wrote:

It can be blessed by Reflect.makeClass(classObject, protoObject) or
similar API.

It can bring lots of new patterns and cowpaths into the language.
If people don't want plain object to be the class, but their existing
object x, they do
Reflect.makeClass(x, (class {...}).prototype);


This can be in some version of `static` syntax in the future.  BUt it 
allows richer outcomes:


Not mere:
  class Foo {
...
static {
  // must be some predefined kind of body
}
  }

but instead:
  claas Foo {
...
static Expr;
  }

where Expr can be any object that would be [[Construct]]ified and bound 
to Foo. So it _can_ be {...} object literal, but it can be anything 
else, existing object that user want to class-ify, a function, ...



and they then can `new x`. They choose what they will use as x for new
operator; because now class is one object and constructor is another.

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


Re: fail-fast object destructuring (don't add more slop to sloppy mode)

2013-01-06 Thread Herby Vojčík



Kevin Smith wrote:


I raised this problem-case, so I want to point out that we could
take other courses:

* Reckon that labels are rare and this won't bite, so let it stand,
just as

a = b
(c)

is a hazard today -- and one that bites much more.

* Don't allow suffix-? to be followed by a newline.


Leaving aside ASI for a moment, there are other issues:

 let v = obj?+(0+1+2+3+4+5+6+7+8+9+...+n):null;


Is it bad to specify that unless it is at the end of (sub)Expression or 
before dot, '?' is treated as first ? in ?: ? Then you have to 
explicitly parenthesize it and that's all.



We don't know whether this is a conditional expression or not until we
get to the : an arbitrary distance away from the ?.  We might be
able to use another cover grammar approach here, but is it worth it?

{ Kevin }


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


Re: fail-fast object destructuring (don't add more slop to sloppy mode)

2013-01-06 Thread Herby Vojčík



Kevin Smith wrote:



Is it bad to specify that unless it is at the end of (sub)Expression
or before dot, '?' is treated as first ? in ?: ? Then you have to
explicitly parenthesize it and that's all.


How do you specify end of expression, though?  You have to consider
ASI here as well.  Is the complexity you suggest worth it?


ASI here as well :-/ hm, yes.
It is complicated.

The only solution I see now is abandon deatiled grammar solution, move 
to higher point of view, treat ? always as ?:, and if the next thing you 
see is a dot or end of subexpression (by any means), make it 
existential ?.


It is probably what you are saying by not worth the complexity.


{ Kevin }


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


Re: Enforcing arity?

2013-01-06 Thread Herby Vojčík



Axel Rauschmayer wrote:

What is the simplest way of enforcing an arity in ES6? Doesn’t it
involve arguments?

function add(x, y) {
if (arguments.length !== 2) throw ...
}

To avoid `argument`, one could:
- ensure a maximum arity by adding a ...rest parameter and checking that
its length is 0.
- ensure a minimum arity, by giving y a default value and checking for it.

Would fail-fast destructuring work?

function add(...args) {
let [x,y] = args;
}


And it this would be possible, it could be in the signature:

  function add(...[x,y,opt?]) {
  }


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


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


Re: fail-fast object destructuring (don't add more slop to sloppy mode)

2013-01-02 Thread Herby Vojčík



Brendan Eich wrote:

I think the refutable-by-default patterns need a ? modifier only for a
leaf identifier in a pattern, not for non-terminal identiifers. For
example:

let {p: {q: r}} = deep_o;

wants to get o.p.q and bind it to r.

With the current irrefutable design, if deep_o = {} or another object
lacking a {q:...} sub-object named p, then this example will fail with a
TypeError even though a shallow example fails-soft (or fails slowly,
really: fails later) by pulling undefined out as the value of p and
binding it to the local (as in the first example in this post).

With a refutable-by-default design, however, it seems to me nonsensical
to support ? on p as well as q in this example:

let {p?: {q?: r}} = deep_o;

because if deep_o has no property p, what should happen? No binding r at
all? Or a let binding named r with value undefined? What if there's no ?
after q in this case -- should that matter?\

We already rejected CoffeeScript's existential operator because of its
lack of compositionality. See
https://mail.mozilla.org/pipermail/es-discuss/2012-September/025232.html
(the section starting ARB: This is non-compositional). I think the
same objection applies to allowing p? in the deep_o case.


I advised adding Null Pattern Object into language in the aforementioned 
thread; and use foo? as `foo == null ? NullPatternObject : foo`.


So you can do `r = o?.p.q`; and it does not fail.
With such construct you could do
  let {p: {q: r}} = deep_o?;


Comments welcome. I'll put this on this month's TC39 meeting agenda.

/be


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


  1   2   3   4   5   >