es-discuss@mozilla.org

2021-03-04 Thread Ron Buckton
This was mentioned up-thread, but I wrote up this proposal several years ago 
(https://github.com/rbuckton/proposal-refs) and am still considering bringing 
it to committee at some point. However, there are a larger set of cross-cutting 
concerns for refs in the context of a proposal like 
https://github.com/rbuckton/proposal-struct (nee. "Typed Objects" or "Value 
Types"), as well as interop with WASM, that also need to be considered. In the 
refs proposal I currently use `ref` rather than `&`, since `&` is often 
ascribed to unmanaged memory addresses in many languages, while `ref` (at least 
in C#) is specifically tied to references to memory managed by the GC. That 
proposal explainer currently includes examples for `ref` variables, parameters, 
expressions, destructuring, and support for reified `Reference` objects.

In userland I currently have https://esfx.js.org/esfx/api/ref.html as a `ref` 
like mechanism:

```js
Import { ref } from "@esfx/ref";

// reference passing

function f(ref_x1, ref_x2) {
console.log(ref_x2.value); // prints 0
ref_x1.value++;
console.log(ref_x2.value); // prints 1
}

let x = 0;
const ref_x1 = ref(() => x, _ => x = _);  // mutable ref to a variable
const ref_x2 = ref(() => x); // immutable ref to a variable
f(ref_x1, ref_x2);
console.log(x); // prints 1

const ar = [0];
const ref_ar0_1 = ref.at(ar, 0); // mutable ref to a property
const ref_ar0_2 = ref.at(ar, 0, /*readonly*/ true); // immutable ref to a 
property
f(ref_ar0_1, ref_ar0_2);
console.log(ar[0]); // prints 1
```

Userland destructuring support isn't feasible, however.

In my refs proposal, you have several constructs:


  *   `ref` expressions - These take a binding and create a reified `Reference` 
object from them. Examples:
 *   `let rx = ref x`
 *   `let rfoo = ref obj.foo`
 *   `let rel = ref ar[0]`
  *   `ref` declarations - These take a reified `Reference` object and create a 
local binding that dereferences them. Examples:
 *   `let ref x2 = rx` - mutable reference
 *   `const ref foo2 = rfoo` - immutable reference
 *   `function f(ref foo) { ... }` - mutable reference argument
 *   `function f(const ref foo) { ... }` - immutable reference argument
  *   Reified `Reference` objects - These are runtime objects with a `value` 
property:
 *   If the reference is mutable, `value` has both a getter and a setter.
 *   If the reference is immutable, `value` has only a getter.

If the `ref` syntax in my proposal were to be adopted, the above example would 
instead read:

```js
function f(ref x1, ref x2) {
console.log(x2); // prints 0
x1++;
console.log(x2); // prints 1
}

let x = 0;
f(ref x, ref x);
console.log(x); // prints 1
```

In Augusto's example, you would have your choice of object passing or variable 
passing:

```js
function foo(ref value) {
  value = 'foo';
}

function second(source) {
  {
  let { ref value } = source; // NOTE `value` is a `Reference` object here
console.log(typeof value); // object
foo(value);
}

// The above would be the same as this
{
let value = ref source.value; // `value` is a `Reference` object here
  console.log(typeof value); // object
foo(value);
  }
}

second({ value: "bar" });
```

I'm still considering the destructuring side of things. Whether you are 
creating a `Reference` or dereferencing it is clear for some patterns:

```js
// (a) `ref` Destructuring Targets
// dereferences `obj.x` if `obj.x` is a `Reference`
let { x: ref x } = obj;

// This is equivalent to the following:
let ref x = obj.x; // Probably not what you want...


// (b) `ref` Destructuring Bindings
// creates a `Reference` for `obj.x` and stores it in `x`, so `x` is a reified 
`Reference`.
let { ref x: x } = obj;

// This is equivalent to the following:
let x = ref obj.x; // Probably not what you want either...


// (c) `ref` Destructuring Targets *and* Bindings
// Create a `Reference` for `obj.x` and dereference it in `x`:
let { ref x: ref x } = obj;

// This is equivalent to the following:
let ref x = ref obj.x; // Probably what you wanted
```

However, this is less clear for shorthand destructuring assignments or array 
destructuring:

```js
let { ref x } = obj; // did you mean (a), (b), or (c) above?
let [ref x] = ar; // did you mean (a), (b), or (c) above?
```

In these two examples, you *probably* want (c), but there are valid reasons for 
wanting (a) or (b) as well. The explainer for the proposal currently chooses 
(a), but I've been reconsidering. None of this is set in stone (since this 
proposal isn't even at Stage 1 yet), and I'm open to suggestions and discussion 
on the issue tracker.

Ron

From: es-discuss  On Behalf Of Andrea Giammarchi
Sent: Thursday, March 4, 2021 12:43 AM
To: Augusto Moura 
Cc: es-discuss 
Subject: [EXTERNAL] Re: Destructuring by &reference

> How will you prevent the passing of the object down the pipe?

```js
const downThePipe = ({&source}) => {
  // you can read source
  source;
  // you can set source
  source = 'bla

Re: Optional Curly Braces in JavaScript

2019-11-03 Thread Ron Buckton
The '_' isn't necessary for chaining expressions, as ',' would already suffice:

```
if (foo==2)
  bar(),
  bar2();
```

Also, '_' is already a valid expression/identifier.

While I'm not generally a fan of eliding braces from everything, I have 
expressed interest in evaluating something like C#'s expression-bodied methods 
for ECMAScript:


```
class C extends B {
  constructor(arg) => super(arg, true);
  toString() => `prop: ${this.prop}`;
  get prop() => this.x + this.y;
}
```


From: es-discuss  on behalf of Ed Saleh 

Sent: Sunday, November 3, 2019 10:48:12 AM
To: Sanford Whiteman ; es-discuss 

Subject: Re: Optional Curly Braces in JavaScript

Update to the proposal:

Since we can't make spaces in JavaScript, the best we can do is use '_' instead.
We will also git rid of ':' after statement in the old version as '_' is enough 
indication and it's more compatible with our current curly braces syntax.

Final result:

```
if (foo==2) _
bar() _
bar2()
```

Which is the same as:
```
if (foo==2)
_ bar();
_ bar2();
```

Basically `_` would allow chaining expressions inside a statement block.

Thank you,

From: es-discuss  on behalf of Sanford Whiteman 

Sent: Sunday, November 3, 2019 1:36:36 AM
To: es-discuss 
Subject: Re: Optional Curly Braces in JavaScript

> the only thing really missing (and which python has) is a builtin
> wasm-sqlite3 library (and specialized/secure file-api's to persist
> sqlite-db-blobs).

Browsers (WPWG, not this group) tried WebSQL. It failed because there
wasn't a competitive bake-off with any other implementations _besides_
SQLite.

If a browser vendor had used another engine, then SQLite might've won
the bake-off and now you'd have what you describe.



___
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: Re: What do you think about a C# 6 like nameof() expression for

2019-06-17 Thread Ron Buckton
ot;y"`.

The 1st question at 
https://esdiscuss.org/topic/what-do-you-think-about-a-c-6-like-nameof-expression-for#content-33<https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fesdiscuss.org%2Ftopic%2Fwhat-do-you-think-about-a-c-6-like-nameof-expression-for%23content-33&data=02%7C01%7Cron.buckton%40microsoft.com%7Ccbc2c8f5e9614533e30e08d6f2e594ef%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636963465244030598&sdata=0jx0f3hXTqN3gfvuWWDh1BiuomZfI3eDdGXetyWSOtk%3D&reserved=0>
 remains:

Without having composed or previously read the source code, at line 1 adjacent 
to ```nameof``` how does the user know that there will be later declared 
variable named ```y```?



On Sun, Jun 16, 2019 at 7:04 AM Isiah Meadows 
mailto:isiahmead...@gmail.com>> wrote:
Here's my opinion:

- If `y` is directly visible in scope and is neither a parameter or
destructured binding, `nameof y` should just evaluate to `"y"`. This
should be agnostic to whether the binding has been declared yet, so in
your example, `x` should be set to `"y"`.
- If `y` is entirely undeclared, it should be a runtime
`ReferenceError` in the same way it is when accessing undefined
globals. So in your second example, I'd expect it to throw before even
attempting assignment

-

Isiah Meadows
cont...@isiahmeadows.com<mailto:cont...@isiahmeadows.com>
www.isiahmeadows.com<https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.isiahmeadows.com&data=02%7C01%7Cron.buckton%40microsoft.com%7Ccbc2c8f5e9614533e30e08d6f2e594ef%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636963465244040592&sdata=ncNlzUB9%2FRJmg7%2Bt1vAM4UtxeAMm62ditqH%2BJh2f2kQ%3D&reserved=0>

On Sun, Jun 16, 2019 at 12:00 AM guest271314 
mailto:guest271...@gmail.com>> wrote:
>
> ```
> const x = nameof y
> const y = 1;
> ```
>
> At line 1 adjacent to ```nameof``` how does the user even know that there is 
> a variable that will be declared named ```y```?
>
> What is the output of ```x``` where there is no variable named ```y``` later 
> declared?
>
> ```
> const x = nameof y
> const z = 1;
> ```
>
> On Sun, Jun 16, 2019 at 12:03 AM Ron Buckton 
> mailto:ron.buck...@microsoft.com>> wrote:
>>
>> > What should occur where the code is
>>
>> It would be "y" in all 3 places.
>>
>> > ... is a proposal for _more_ than only getting the _name_ of an _declared_ 
>> > and _initialized_ variable?
>>
>> It is a proposal for getting the name of a _declared_ variable. Whether it 
>> is _initialized_ does not matter.
>>
>> > Should a ```RefefenceError``` _not_ be thrown simple because ```nameof``` 
>> > is used?
>>
>> No, an error is not thrown. ECMAScript is much more nuanced. Block scoped 
>> variables from 'let' or 'const' exist and can be *referenced* (via closure 
>> or export, currently) anywhere within the same block scope, even before they 
>> are initialized. Until they have been *initialized* (the line of code 
>> contain the declaration has been reached and evaluated), they exist in a 
>> "Temporal Dead Zone" (TDZ). Attempting to *dereference* them (i.e. access or 
>> store a value) while in this TDZ is what results in the ReferenceError.
>>
>> At no point does the `nameof` operator *dereference* the variable, so no 
>> error need be thrown.
>>
>> From: guest271314
>> Sent: Saturday, June 15, 4:29 PM
>> Subject: Re: Re: What do you think about a C# 6 like nameof() expression for
>> To: Ron Buckton
>> Cc: es-discuss@mozilla.org<mailto:es-discuss@mozilla.org>
>>
>>
>>
>>
>> What should occur where the code is
>>
>> ```
>> const x = nameof y
>> await new Promise(resolve => setTimeout(resolve, 10)); // should x be 
>> "y" here?
>> await new Promise(resolve => setTimeout(resolve, 20)); // should x be 
>> "y" here?
>> await Promise.all([new Promise(resolve => setTimeout(resolve, 30)), 
>> ...doStuff()]); // should x be "y" here?
>> const y = 1;
>> ```
>>
>> ?
>>
>> The immediately invoked arrow function example (where a 
>> ```RefeferenceError``` is thrown) appears to demonstrate that to output the 
>> expected result of ```nameof``` within the context of the code example
>>
>> ```
>> const x = nameof y
>> const y = 1;
>> ```
>>
>> is a proposal for _more_ than only getting the _name_ of an _declared_ and 
>> _initialized_ variable?
>>
>> Should a ```RefefenceError``` _not_ be thrown simple because ```nameof``` is 
>> used?
>>
>> On Sat, Jun 

RE: Re: What do you think about a C# 6 like nameof() expression for

2019-06-17 Thread Ron Buckton
> How is VSCode related to JavaScript?

You have ignored the context from Jordan’s email (emphasis added):

>> again, `Object.keys({ y })[0]` will give you the string `y`, and will 
>> survive refactoring tools. you can even do `function nameof(obj) { return 
>> Object.keys(obj)[0]; }` and then `nameof({ y })`.

VSCode is a popular editor that supports JavaScript *and* is a refactoring 
tool. Rename refactoring was the subject I was responding to.

There are a number of reasons VSCode has implemented rename refactoring in this 
fashion. Not the least of which is that an editor cannot fully understand user 
intent. Let us say, for example, you are working with Gulp:

```
const cwd /*1*/ = ".";
gulp.src("*.js", { cwd /*2*/ });
```

If you were to rename `cwd` at (1) and it *also* renamed the `cwd` property at 
(2), you would have introduced an error in the call because a `cwd` option to 
gulp has a special meaning. Since the editor doesn’t know the intent of the 
user may be to rename *both* symbols, it remains conservative and choses only 
to rename the binding and its references, producing:

```
const currentDir = ".";
gulp.src("*.js", { cwd: currentDir });
```

There is also the issue of collisions:

```
const foo /*1*/ = 1;
f({ foo /*2*/, bar: 2 });
```

If I were to use a refactoring tool to rename `foo` at (1) to `bar`, it would 
*not* be safe to rename the property at (2) as well as it would introduce a 
semantic error that would prevent the entire script from executing.

In the context of Jordan’s email, that means that `Object.keys({ y })[0]` would 
*not* necessarily survive refactoring tools.

From: es-discuss  On Behalf Of guest271314
Sent: Monday, June 17, 2019 7:40 AM
Cc: es-discuss@mozilla.org
Subject: Re: Re: What do you think about a C# 6 like nameof() expression for

> In VSCode, if you rename ‘foo’ to ‘bar’ at /1/, you get this:

How is VSCode related to JavaScript?

Is the proposal really based on creating ```nameof``` in JavaScript to 
workaround output at a text editor?

Why not file a bug with the individuals who write the code for VSCode or just 
write a text editor code from scratch which does what you want as to 
"refactoring". Or write the code by hand and test the code  to avoid having to 
rely on _any_ text editor to catch your mistakes?


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


RE: Re: What do you think about a C# 6 like nameof() expression for

2019-06-16 Thread Ron Buckton
t question at 
https://esdiscuss.org/topic/what-do-you-think-about-a-c-6-like-nameof-expression-for#content-33<https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fesdiscuss.org%2Ftopic%2Fwhat-do-you-think-about-a-c-6-like-nameof-expression-for%23content-33&data=02%7C01%7Cron.buckton%40microsoft.com%7Ccbc2c8f5e9614533e30e08d6f2e594ef%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636963465244030598&sdata=0jx0f3hXTqN3gfvuWWDh1BiuomZfI3eDdGXetyWSOtk%3D&reserved=0>
 remains:

Without having composed or previously read the source code, at line 1 adjacent 
to ```nameof``` how does the user know that there will be later declared 
variable named ```y```?



On Sun, Jun 16, 2019 at 7:04 AM Isiah Meadows 
mailto:isiahmead...@gmail.com>> wrote:
Here's my opinion:

- If `y` is directly visible in scope and is neither a parameter or
destructured binding, `nameof y` should just evaluate to `"y"`. This
should be agnostic to whether the binding has been declared yet, so in
your example, `x` should be set to `"y"`.
- If `y` is entirely undeclared, it should be a runtime
`ReferenceError` in the same way it is when accessing undefined
globals. So in your second example, I'd expect it to throw before even
attempting assignment

-

Isiah Meadows
cont...@isiahmeadows.com<mailto:cont...@isiahmeadows.com>
www.isiahmeadows.com<https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.isiahmeadows.com&data=02%7C01%7Cron.buckton%40microsoft.com%7Ccbc2c8f5e9614533e30e08d6f2e594ef%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636963465244040592&sdata=ncNlzUB9%2FRJmg7%2Bt1vAM4UtxeAMm62ditqH%2BJh2f2kQ%3D&reserved=0>

On Sun, Jun 16, 2019 at 12:00 AM guest271314 
mailto:guest271...@gmail.com>> wrote:
>
> ```
> const x = nameof y
> const y = 1;
> ```
>
> At line 1 adjacent to ```nameof``` how does the user even know that there is 
> a variable that will be declared named ```y```?
>
> What is the output of ```x``` where there is no variable named ```y``` later 
> declared?
>
> ```
> const x = nameof y
> const z = 1;
> ```
>
> On Sun, Jun 16, 2019 at 12:03 AM Ron Buckton 
> mailto:ron.buck...@microsoft.com>> wrote:
>>
>> > What should occur where the code is
>>
>> It would be "y" in all 3 places.
>>
>> > ... is a proposal for _more_ than only getting the _name_ of an _declared_ 
>> > and _initialized_ variable?
>>
>> It is a proposal for getting the name of a _declared_ variable. Whether it 
>> is _initialized_ does not matter.
>>
>> > Should a ```RefefenceError``` _not_ be thrown simple because ```nameof``` 
>> > is used?
>>
>> No, an error is not thrown. ECMAScript is much more nuanced. Block scoped 
>> variables from 'let' or 'const' exist and can be *referenced* (via closure 
>> or export, currently) anywhere within the same block scope, even before they 
>> are initialized. Until they have been *initialized* (the line of code 
>> contain the declaration has been reached and evaluated), they exist in a 
>> "Temporal Dead Zone" (TDZ). Attempting to *dereference* them (i.e. access or 
>> store a value) while in this TDZ is what results in the ReferenceError.
>>
>> At no point does the `nameof` operator *dereference* the variable, so no 
>> error need be thrown.
>>
>> From: guest271314
>> Sent: Saturday, June 15, 4:29 PM
>> Subject: Re: Re: What do you think about a C# 6 like nameof() expression for
>> To: Ron Buckton
>> Cc: es-discuss@mozilla.org<mailto:es-discuss@mozilla.org>
>>
>>
>>
>>
>> What should occur where the code is
>>
>> ```
>> const x = nameof y
>> await new Promise(resolve => setTimeout(resolve, 10)); // should x be 
>> "y" here?
>> await new Promise(resolve => setTimeout(resolve, 20)); // should x be 
>> "y" here?
>> await Promise.all([new Promise(resolve => setTimeout(resolve, 30)), 
>> ...doStuff()]); // should x be "y" here?
>> const y = 1;
>> ```
>>
>> ?
>>
>> The immediately invoked arrow function example (where a 
>> ```RefeferenceError``` is thrown) appears to demonstrate that to output the 
>> expected result of ```nameof``` within the context of the code example
>>
>> ```
>> const x = nameof y
>> const y = 1;
>> ```
>>
>> is a proposal for _more_ than only getting the _name_ of an _declared_ and 
>> _initialized_ variable?
>>
>> Should a ```RefefenceError``` _not_ be thrown simple because ```nameof``` is 
>> used?
>>
>> On Sat, Jun 15, 2019 at 11:16 PM

Re: Re: What do you think about a C# 6 like nameof() expression for

2019-06-15 Thread Ron Buckton
> What should occur where the code is

It would be "y" in all 3 places.

> ... is a proposal for _more_ than only getting the _name_ of an _declared_ 
> and _initialized_ variable?

It is a proposal for getting the name of a _declared_ variable. Whether it is 
_initialized_ does not matter.

> Should a ```RefefenceError``` _not_ be thrown simple because ```nameof``` is 
> used?

No, an error is not thrown. ECMAScript is much more nuanced. Block scoped 
variables from 'let' or 'const' exist and can be *referenced* (via closure or 
export, currently) anywhere within the same block scope, even before they are 
initialized. Until they have been *initialized* (the line of code contain the 
declaration has been reached and evaluated), they exist in a "Temporal Dead 
Zone" (TDZ). Attempting to *dereference* them (i.e. access or store a value) 
while in this TDZ is what results in the ReferenceError.

At no point does the `nameof` operator *dereference* the variable, so no error 
need be thrown.

From: guest271314
Sent: Saturday, June 15, 4:29 PM
Subject: Re: Re: What do you think about a C# 6 like nameof() expression for
To: Ron Buckton
Cc: es-discuss@mozilla.org




What should occur where the code is

```
const x = nameof y
await new Promise(resolve => setTimeout(resolve, 10)); // should x be "y" 
here?
await new Promise(resolve => setTimeout(resolve, 20)); // should x be "y" 
here?
await Promise.all([new Promise(resolve => setTimeout(resolve, 30)), 
...doStuff()]); // should x be "y" here?
const y = 1;
```

?

The immediately invoked arrow function example (where a ```RefeferenceError``` 
is thrown) appears to demonstrate that to output the expected result of 
```nameof``` within the context of the code example

```
const x = nameof y
const y = 1;
```

is a proposal for _more_ than only getting the _name_ of an _declared_ and 
_initialized_ variable?

Should a ```RefefenceError``` _not_ be thrown simple because ```nameof``` is 
used?

On Sat, Jun 15, 2019 at 11:16 PM Ron Buckton 
mailto:ron.buck...@microsoft.com>> wrote:
```
const x = nameof y
const y = 1;
```

`x` would have the value “y”. It would not matter if `y` were initialized or 
had yet been reached during execution. It does not deviate from the purpose of 
`let` or `const`, because you are not accessing the value of the identifier.

Also consider that this is legal ECMAScript in a module:

```
export { y }
const y = 1;
```

The binding for `y` exists within the same block scope, it just has not yet 
been initialized. Exporting it via `export { y }`, closing over it via `() => 
y`, or accessing it via `nameof y` would all be the same. In all three cases 
you are accessing the *binding* of `y`, not the *value* of `y`. Even in the `() 
=> y` case, you don’t access the *value* of `y` until you execute the function.

From: guest271314 mailto:guest271...@gmail.com>>
Sent: Saturday, June 15, 2019 3:57 PM
To: Ron Buckton mailto:ron.buck...@microsoft.com>>
Cc: es-discuss@mozilla.org<mailto:es-discuss@mozilla.org>
Subject: Re: Re: What do you think about a C# 6 like nameof() expression for

> Sorry, I meant to say “not entirely correct”.

You have not yet confirmed if in fact the expected output is referencing a 
variable declared using ```const``` on the current line _before_ initialization 
_on the next line_.

That example appears to deviate from the purpose and usage of ```const```, 
beyond the scope of ```nameof```, and if were implemented, a 
```ReferenceError``` should _not_ be thrown when a ```const``` variable that 
has yet to be initialized _on the next line_ is referred to _on the current 
line_?

Aside from that example, the code which essentially already implements 
```nameof``` should be able to be found in the code which implements 
```ReferenceError``` relevant to ```const```.

On Sat, Jun 15, 2019 at 10:47 PM Ron Buckton 
mailto:ron.buck...@microsoft.com>> wrote:
Sorry, I meant to say “not entirely correct”.

From: Ron Buckton
Sent: Saturday, June 15, 2019 3:03 PM
To: guest271314 mailto:guest271...@gmail.com>>
Cc: es-discuss@mozilla.org<mailto:es-discuss@mozilla.org>
Subject: RE: Re: What do you think about a C# 6 like nameof() expression for

> At that point in the example code the identifer ```y``` does not exist.

That is not entirely incorrect. The identifier `y` exists, but its binding has 
not been initialized, otherwise you couldn’t refer to y in this case:



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


RE: Re: What do you think about a C# 6 like nameof() expression for

2019-06-15 Thread Ron Buckton
```
const x = nameof y
const y = 1;
```

`x` would have the value “y”. It would not matter if `y` were initialized or 
had yet been reached during execution. It does not deviate from the purpose of 
`let` or `const`, because you are not accessing the value of the identifier.

Also consider that this is legal ECMAScript in a module:

```
export { y }
const y = 1;
```

The binding for `y` exists within the same block scope, it just has not yet 
been initialized. Exporting it via `export { y }`, closing over it via `() => 
y`, or accessing it via `nameof y` would all be the same. In all three cases 
you are accessing the *binding* of `y`, not the *value* of `y`. Even in the `() 
=> y` case, you don’t access the *value* of `y` until you execute the function.

From: guest271314 
Sent: Saturday, June 15, 2019 3:57 PM
To: Ron Buckton 
Cc: es-discuss@mozilla.org
Subject: Re: Re: What do you think about a C# 6 like nameof() expression for

> Sorry, I meant to say “not entirely correct”.

You have not yet confirmed if in fact the expected output is referencing a 
variable declared using ```const``` on the current line _before_ initialization 
_on the next line_.

That example appears to deviate from the purpose and usage of ```const```, 
beyond the scope of ```nameof```, and if were implemented, a 
```ReferenceError``` should _not_ be thrown when a ```const``` variable that 
has yet to be initialized _on the next line_ is referred to _on the current 
line_?

Aside from that example, the code which essentially already implements 
```nameof``` should be able to be found in the code which implements 
```ReferenceError``` relevant to ```const```.

On Sat, Jun 15, 2019 at 10:47 PM Ron Buckton 
mailto:ron.buck...@microsoft.com>> wrote:
Sorry, I meant to say “not entirely correct”.

From: Ron Buckton
Sent: Saturday, June 15, 2019 3:03 PM
To: guest271314 mailto:guest271...@gmail.com>>
Cc: es-discuss@mozilla.org<mailto:es-discuss@mozilla.org>
Subject: RE: Re: What do you think about a C# 6 like nameof() expression for

> At that point in the example code the identifer ```y``` does not exist.

That is not entirely incorrect. The identifier `y` exists, but its binding has 
not been initialized, otherwise you couldn’t refer to y in this case:

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


RE: Re: What do you think about a C# 6 like nameof() expression for

2019-06-15 Thread Ron Buckton
Sorry, I meant to say “not entirely correct”.

From: Ron Buckton
Sent: Saturday, June 15, 2019 3:03 PM
To: guest271314 
Cc: es-discuss@mozilla.org
Subject: RE: Re: What do you think about a C# 6 like nameof() expression for

> At that point in the example code the identifer ```y``` does not exist.

That is not entirely incorrect. The identifier `y` exists, but its binding has 
not been initialized, otherwise you couldn’t refer to y in this case:

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


RE: Re: What do you think about a C# 6 like nameof() expression for

2019-06-15 Thread Ron Buckton
> At that point in the example code the identifer ```y``` does not exist.

That is not entirely incorrect. The identifier `y` exists, but its binding has 
not been initialized, otherwise you couldn’t refer to y in this case:

```
const f = () => y;
let y = 1;
```

> That fact can be utilized for an alternative approach to meet requirement of 
> "Case 1. Function guard.".

I don’t disagree that there are “alternative approaches” to ‘nameof’ for many 
cases, but they all incur overhead.

At the end of the day, ‘nameof’ is a convenience feature that provides an 
incremental “quality of life” improvement, much like shorthand property 
assignments were a convenience feature (i.e. how hard is it to write `{ foo: 
foo }`). It’s not something that would be as much of a game changer to the 
language as async/await or yield were, but it would be a fairly easily spec’d 
and nice-to-have capability.

From: guest271314 
Sent: Saturday, June 15, 2019 2:50 PM
To: Ron Buckton 
Cc: es-discuss@mozilla.org
Subject: Re: Re: What do you think about a C# 6 like nameof() expression for

> It doesn’t matter what the value of ‘y’ is, just what the lexical name of `y` 
> is. `nameof` wouldn’t refer to `y` as an expression, its just pointing to the 
> identifier.

Was not referring to the _value_ of ```y```. At that point in the example code 
the identifer ```y``` does not exist. That is, unless there was an expected 
presumption that ```y``` was defined globally prior to the ```const y = 1;``` 
declaration at the next line. Even then a variable declared using ```const``` 
cannot be referenced before "lexical declaration" or "initialization". That 
fact can be utilized for an alternative approach to meet requirement of "Case 
1. Function guard.". Tested at Chromium 76 and Firefox 69. Have not used MS 
browser (or browserstack) in some time. Have not tried the code at Safari 
either, though the code is capable of adjustment for any JavaScript environment 
which throws a ```ReferenceError``` under the same case

```
function func1(param1, param2, param3, userName, param4, param5) {
  if (userName === undefined) {
try {
  // throws ReferenceError
  // Firefox 69: ReferenceError: "can't access lexical declaration 
`userName' before initialization"
  // Chromium 76: ReferenceError: Cannot access 'userName' before 
initialization
  const userName = userName;
} catch (e) {
  // match identifier at Firefox, Chromium ReferenceError message
  // adjust RegExp for IE/Edge, Safari, etc.
  const nameof = e.message.match(/(?!`|')[^\s]+(?=')/g).pop();
  throw new Error(`"Argument cannot be null: ${nameof}"`);
}
  } else {
// do stuff
console.log(userName);
  }
}

try {
  func1(1, 2, 3); // throws error
} catch (e) {
  console.error(e); // get name of variable identifier
}

try {
  func1(1, 2, 3, 4); // logs userName at console
} catch (e) {
  console.error(e); // should not be reached
}
```

On Sat, Jun 15, 2019 at 9:37 PM Ron Buckton 
mailto:ron.buck...@microsoft.com>> wrote:
It doesn’t matter what the value of ‘y’ is, just what the lexical name of `y` 
is. `nameof` wouldn’t refer to `y` as an expression, its just pointing to the 
identifier.

From: guest271314 mailto:guest271...@gmail.com>>
Sent: Friday, June 14, 2019 10:03 PM
To: Ron Buckton mailto:ron.buck...@microsoft.com>>
Cc: es-discuss@mozilla.org<mailto:es-discuss@mozilla.org>
Subject: Re: Re: What do you think about a C# 6 like nameof() expression for

> I’m not sure I understand what you mean by “false-positive” in this instance.

Was referring to


const x = nameof y; // "y"

const y = 1;

Where ```y``` is ```undefined``` an error is not expected to be thrown? Is 
```y``` declared globally, using ```const``` or ```let```, or not at all? The 
use case  described by OP


function func1(param1, param2, param3, userName, param4, param5) {

   if (userName == undefined) {

   throw new ArgumentNullError(nameof userName); // `ArgumentNullError`

is a custom error, derived from `Error`, composes error message like

"Argument cannot be null: userName".

   }
checks if ```userName``` was ```undefined``` before using ```nameof```.  If 
error checking is a substantial portion of the proposal, why should an error 
(```y``` being ```undefined``` though referenced) be ignored when referencing 
an undefined identifier though concentrate on coercing a name from a different 
potentially undefined property?

Consider this case:
```
const someObject = { value: 1 };
function setValue(value /*1*/) {
  if (typeof value /*2*/ !== "number") throw new TypeError(`Number expected: 
${nameof value /*3*/}`);
  someObject["value" /*4*/] = value /*5*/;
}
```
If you rename the parameter `value` of the function `setValue` in an editor 
with a rename refactoring, you want to rename the sy

RE: Re: What do you think about a C# 6 like nameof() expression for

2019-06-15 Thread Ron Buckton
It doesn’t matter what the value of ‘y’ is, just what the lexical name of `y` 
is. `nameof` wouldn’t refer to `y` as an expression, its just pointing to the 
identifier.

From: guest271314 
Sent: Friday, June 14, 2019 10:03 PM
To: Ron Buckton 
Cc: es-discuss@mozilla.org
Subject: Re: Re: What do you think about a C# 6 like nameof() expression for

> I’m not sure I understand what you mean by “false-positive” in this instance.

Was referring to


const x = nameof y; // "y"

const y = 1;

Where ```y``` is ```undefined``` an error is not expected to be thrown? Is 
```y``` declared globally, using ```const``` or ```let```, or not at all? The 
use case  described by OP


function func1(param1, param2, param3, userName, param4, param5) {

   if (userName == undefined) {

   throw new ArgumentNullError(nameof userName); // `ArgumentNullError`

is a custom error, derived from `Error`, composes error message like

"Argument cannot be null: userName".

   }
checks if ```userName``` was ```undefined``` before using ```nameof```.  If 
error checking is a substantial portion of the proposal, why should an error 
(```y``` being ```undefined``` though referenced) be ignored when referencing 
an undefined identifier though concentrate on coercing a name from a different 
potentially undefined property?

Consider this case:
```
const someObject = { value: 1 };
function setValue(value /*1*/) {
  if (typeof value /*2*/ !== "number") throw new TypeError(`Number expected: 
${nameof value /*3*/}`);
  someObject["value" /*4*/] = value /*5*/;
}
```
If you rename the parameter `value` of the function `setValue` in an editor 
with a rename refactoring, you want to rename the symbols at 1, 2, 3, and 5, 
but not the string at 4.

Not gathering the purpose or value of ```nameof``` usage in that case. If the 
value is not a "number" then why does the value or name matter?

Since the primary use case appears to be an editor environment, why cannot the 
editor be programmed to recognize the custom JavaScript ```nameof function 
or operator? Then it would not matter if this board concurred with the 
```nameof``` functionality or not. Both CLI and GUI editors (and JavaScript) 
are generally extensible. FWIW, some time ago incorporated features into gedit 
for HTML templates; should be a similar process to create custom scripts for 
the various editor environments where users rely on such programs for code 
composition; now simply write the code by hand and test in different 
environments, without taking the time to customize or rely on an editor - take 
the time to test the code where the code will actually be run where errors, if 
any, can be evaluated in the context in which a specific output is expected. To 
each their own. What needs to be implemented outside of what the users which 
advocate for ```nameof``` cannot implement themselves?

As mentioned earlier do not rely on "an editor with name refactoring" to 
compose code. The code has to be tested (outside of the editor environments) 
anyway. Test the code itself, here, not the editor.

On Fri, Jun 14, 2019 at 9:49 PM Ron Buckton 
mailto:ron.buck...@microsoft.com>> wrote:
I’m not sure I understand what you mean by “false-positive” in this instance.

Consider this case:

```
const someObject = { value: 1 };
function setValue(value /*1*/) {
  if (typeof value /*2*/ !== "number") throw new TypeError(`Number expected: 
${nameof value /*3*/}`);
  someObject["value" /*4*/] = value /*5*/;
}
```

If you rename the parameter `value` of the function `setValue` in an editor 
with a rename refactoring, you want to rename the symbols at 1, 2, 3, and 5, 
but not the string at 4.

Ron

From: guest271314 mailto:guest271...@gmail.com>>
Sent: Friday, June 14, 2019 2:43 PM
To: Ron Buckton mailto:ron.buck...@microsoft.com>>
Cc: es-discuss@mozilla.org<mailto:es-discuss@mozilla.org>
Subject: Re: Re: What do you think about a C# 6 like nameof() expression for

How is that behaviour related to the use cases presented by OP? Would such 
behaviour not lead to false-positive relevant to the 2 use cases?

On Fri, Jun 14, 2019 at 9:36 PM Ron Buckton 
mailto:ron.buck...@microsoft.com>> wrote:
> `nameof whatever` → `Object.keys({ whatever })[0]`, but I'm a bit confused 
> why it'd be better to type `nameof foo` in code, rather than `'foo'` - if you 
> change `foo` to `bar`, you have to change both of them anyways.

If you are using an editor that supports rename refactoring, its generally 
easier to rename the symbol `foo` and have all references (including `nameof 
foo`) be updated. You cannot safely automatically rename `'foo'` to `'bar'` 
since an editor or language service cannot guarantee that by the string `'foo'` 
you meant “the text of the identifier `foo`”.

From: es-discuss 
mailto:es-discuss-boun...@mozilla.org>> On 
B

RE: Re: What do you think about a C# 6 like nameof() expression for

2019-06-14 Thread Ron Buckton
I’m not sure I understand what you mean by “false-positive” in this instance.

Consider this case:

```
const someObject = { value: 1 };
function setValue(value /*1*/) {
  if (typeof value /*2*/ !== "number") throw new TypeError(`Number expected: 
${nameof value /*3*/}`);
  someObject["value" /*4*/] = value /*5*/;
}
```

If you rename the parameter `value` of the function `setValue` in an editor 
with a rename refactoring, you want to rename the symbols at 1, 2, 3, and 5, 
but not the string at 4.

Ron

From: guest271314 
Sent: Friday, June 14, 2019 2:43 PM
To: Ron Buckton 
Cc: es-discuss@mozilla.org
Subject: Re: Re: What do you think about a C# 6 like nameof() expression for

How is that behaviour related to the use cases presented by OP? Would such 
behaviour not lead to false-positive relevant to the 2 use cases?

On Fri, Jun 14, 2019 at 9:36 PM Ron Buckton 
mailto:ron.buck...@microsoft.com>> wrote:
> `nameof whatever` → `Object.keys({ whatever })[0]`, but I'm a bit confused 
> why it'd be better to type `nameof foo` in code, rather than `'foo'` - if you 
> change `foo` to `bar`, you have to change both of them anyways.

If you are using an editor that supports rename refactoring, its generally 
easier to rename the symbol `foo` and have all references (including `nameof 
foo`) be updated. You cannot safely automatically rename `'foo'` to `'bar'` 
since an editor or language service cannot guarantee that by the string `'foo'` 
you meant “the text of the identifier `foo`”.

From: es-discuss 
mailto:es-discuss-boun...@mozilla.org>> On 
Behalf Of Jordan Harband
Sent: Friday, June 14, 2019 2:29 PM
To: guest271314 mailto:guest271...@gmail.com>>
Cc: es-discuss mailto:es-discuss@mozilla.org>>
Subject: Re: Re: What do you think about a C# 6 like nameof() expression for

`nameof whatever` → `Object.keys({ whatever })[0]`, but I'm a bit confused why 
it'd be better to type `nameof foo` in code, rather than `'foo'` - if you 
change `foo` to `bar`, you have to change both of them anyways.

On Fri, Jun 14, 2019 at 1:31 PM guest271314 
mailto:guest271...@gmail.com>> wrote:
Am neither for nor against the proposal. Do not entertain "like"s or "dislike"s 
in any field of endeavor. Am certainly not in a position to prohibit anything 
relevant JavaScript. Do what thou wilt shall be the whole of the Law.

Have yet to view a case where code will be "broken" by ```nameof``` not being a 
JavaScript feature. "robustness", as already mentioned, is a subjective 
adjective that is not capable of being objectively evaluated as to code itself. 
That description is based on preference or choice.

In lieu of the proposal being specificed, use the posted code example of 
```Object.keys()``` that "works".

```
function func1({userName = void 0} = {}) {
  console.assert(userName !== undefined, [{userName}, 'property needs to be 
defined'])
}
```

provides a direct indication that the property value is required to be defined. 
Note that the example code posted thus far does not first check if 
```options``` is passed at all, for which ```nameof``` will not provide any 
asssitance.

Usually try to meet requirement by means already available in FOSS browsers. 
Have no interest in TypeScript or using an IDE.

FWIW, have no objection to the proposal.

On Fri, Jun 14, 2019 at 7:53 PM Stas Berkov 
mailto:stas.ber...@gmail.com>> wrote:
guest271314, what is you point against `nameof` feature?

If you don't like it - don't use it. Why prohibit this feature for
those who find it beneficial?

I see `nameof` beneficial in following cases

Case 1. Function guard.
```
function func1(options) {
...
   if (options.userName == undefined) {
   throw new ParamNullError(nameof options.userName); //
`ParamNullError` is a custom error, derived from `Error`, composes
error message like "Parameter cannot be null: userName".
 // `Object.keys({options.userName})[0]` will not work here
   }
}
```

Case 2. Accessing property extended info
Those ES functions that accept field name as string.
e.g.
```
const descriptor1 = Object.getOwnPropertyDescriptor(object1, 'property1');
```
vs
```
const descriptor1 = Object.getOwnPropertyDescriptor(object1, nameof
object1.property1);
 // `Object.keys({options1.property1})[0]` will not work here
```
2nd variant (proposed) has more chances not to be broken during
refactoring (robustness).

It would make devs who use IDE more productive and make their life
easier. Why not give them such possiblity and make them happy?
___
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


RE: Re: What do you think about a C# 6 like nameof() expression for

2019-06-14 Thread Ron Buckton
> `nameof whatever` → `Object.keys({ whatever })[0]`, but I'm a bit confused 
> why it'd be better to type `nameof foo` in code, rather than `'foo'` - if you 
> change `foo` to `bar`, you have to change both of them anyways.

If you are using an editor that supports rename refactoring, its generally 
easier to rename the symbol `foo` and have all references (including `nameof 
foo`) be updated. You cannot safely automatically rename `'foo'` to `'bar'` 
since an editor or language service cannot guarantee that by the string `'foo'` 
you meant “the text of the identifier `foo`”.

From: es-discuss  On Behalf Of Jordan Harband
Sent: Friday, June 14, 2019 2:29 PM
To: guest271314 
Cc: es-discuss 
Subject: Re: Re: What do you think about a C# 6 like nameof() expression for

`nameof whatever` → `Object.keys({ whatever })[0]`, but I'm a bit confused why 
it'd be better to type `nameof foo` in code, rather than `'foo'` - if you 
change `foo` to `bar`, you have to change both of them anyways.

On Fri, Jun 14, 2019 at 1:31 PM guest271314 
mailto:guest271...@gmail.com>> wrote:
Am neither for nor against the proposal. Do not entertain "like"s or "dislike"s 
in any field of endeavor. Am certainly not in a position to prohibit anything 
relevant JavaScript. Do what thou wilt shall be the whole of the Law.

Have yet to view a case where code will be "broken" by ```nameof``` not being a 
JavaScript feature. "robustness", as already mentioned, is a subjective 
adjective that is not capable of being objectively evaluated as to code itself. 
That description is based on preference or choice.

In lieu of the proposal being specificed, use the posted code example of 
```Object.keys()``` that "works".

```
function func1({userName = void 0} = {}) {
  console.assert(userName !== undefined, [{userName}, 'property needs to be 
defined'])
}
```

provides a direct indication that the property value is required to be defined. 
Note that the example code posted thus far does not first check if 
```options``` is passed at all, for which ```nameof``` will not provide any 
asssitance.

Usually try to meet requirement by means already available in FOSS browsers. 
Have no interest in TypeScript or using an IDE.

FWIW, have no objection to the proposal.

On Fri, Jun 14, 2019 at 7:53 PM Stas Berkov 
mailto:stas.ber...@gmail.com>> wrote:
guest271314, what is you point against `nameof` feature?

If you don't like it - don't use it. Why prohibit this feature for
those who find it beneficial?

I see `nameof` beneficial in following cases

Case 1. Function guard.
```
function func1(options) {
...
   if (options.userName == undefined) {
   throw new ParamNullError(nameof options.userName); //
`ParamNullError` is a custom error, derived from `Error`, composes
error message like "Parameter cannot be null: userName".
 // `Object.keys({options.userName})[0]` will not work here
   }
}
```

Case 2. Accessing property extended info
Those ES functions that accept field name as string.
e.g.
```
const descriptor1 = Object.getOwnPropertyDescriptor(object1, 'property1');
```
vs
```
const descriptor1 = Object.getOwnPropertyDescriptor(object1, nameof
object1.property1);
 // `Object.keys({options1.property1})[0]` will not work here
```
2nd variant (proposed) has more chances not to be broken during
refactoring (robustness).

It would make devs who use IDE more productive and make their life
easier. Why not give them such possiblity and make them happy?
___
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: Re: What do you think about a C# 6 like nameof() expression for

2019-06-14 Thread Ron Buckton


> Interesting. ```y``` would be able to be evaluated before ```y``` is defined?
I very explicitly stated that `nameof y` would *not* evaluate its operand. 
Evaluation of `nameof` would merely result in a string containing the name of 
the binding referenced by the operand.

From: es-discuss  On Behalf Of guest271314
Sent: Friday, June 14, 2019 12:09 PM
To: Stas Berkov 
Cc: es-discuss@mozilla.org
Subject: Re: Re: What do you think about a C# 6 like nameof() expression for

> A module namespace isn’t an instance of Module, it’s a module namespace spec 
> object. If it has a name member, that is because the module you imported has 
> an exported binding called name. But what kind of thing it is isn’t what 
> matters.

If ```Object.getOwnPropertyDescriptors(ns)``` is used within ```

RE: Re: What do you think about a C# 6 like nameof() expression for

2019-06-14 Thread Ron Buckton
Since `nameof` does not actually evaluate anything, the following would be 
legal:

```
const x = nameof y; // "y"
const y = 1;
```

However, the shorthand property name workaround is not legal due to TDZ:

```
const x = Object.keys({y})[0]; // error due to TDZ
const y = 1;
```

With the shortand property name workaround you also run into the added runtime 
overhead of:

  *   Constructing an object (`{y}`)
  *   Looking up a property (`Object.keys`)
  *   Calling a function (`Object.keys`)
  *   Allocating an array
  *   Indexing into the array

Whereas `nameof` has *no* runtime overhead, because it would be handled during 
static semantics.


From: es-discuss  On Behalf Of guest271314
Sent: Friday, June 14, 2019 11:17 AM
To: Stas Berkov 
Cc: es-discuss@mozilla.org
Subject: Re: Re: What do you think about a C# 6 like nameof() expression for

Terms such as "more robust", "Less fragile." , "Less mess." are subjective. 
"Fragile" how? What is meant by "mess"?

If the proposal is that ```nameof``` is briefer than using shorthand property 
names or computed property names to get an identifier as a string, then 
```nameof``` would be less code.

> You can rename field/property without fear you break something (using IDE 
> refactoring tools).

The use case appears to be within the context of an IDE?

For users that roll their own code by hand at a text editor and do not use an 
IDE for composing code (or relying on an IDE for logging errors), am not able 
to discern how ```nameof``` is different than using 
```Object.getOwnPropertyDescriptors(other).name.value``` or 
```Object.keys({userName})[0]```. The actual code will need to be tested in 
different browsers anyway before deployment to get the actual results.

If a user has decided they _have_ to use some form of a dynamic "IDE" to 
compose code and log errors - while they are writing the code, they can open 
DevTools at Chromium or Chrome then select ```Sources``` => ```Snippets``` => 
```New snippet```, where

```
const n = 123;
const n = 456;
```

will highlight the line where the error occurs - during writing the code - the 
as a red circle with a transparent "x" in the middle

```Uncaught SyntaxError: Identifier 'n' has already been declared

To run the code press ```ctrl+enter```.




On Fri, Jun 14, 2019 at 5:48 PM Stas Berkov 
mailto:stas.ber...@gmail.com>> wrote:
Less fragile. Less mess. You can rename field/property without fear you break 
something (using IDE refactoring tools).
With high probablity you will break something when you refactor and have fields 
hardcoded as strings.
Someone can object that you can rename strings as well.
Issue here that you can ocassionally change non-related strings that should not 
be changed even they match or have matching substring.

On Fri, Jun 14, 2019 at 9:38 PM guest271314 
mailto:guest271...@gmail.com>> wrote:
Is Case 1 equivalent to a briefer version of

```
   if (userName == undefined) {
   throw new Error(`Argument cannot be null: 
${Object.keys({userName})[0]}`);
   }
```

?

If not, how is ```nameof``` different?

What is the difference between the use of 
```message.hasOwnProperty(property)``` and ```nameof msg.expiration_utc_time```?

> You get more robust code.

How is "robust" objectively determined?




On Fri, Jun 14, 2019 at 5:21 PM Stas Berkov 
mailto:stas.ber...@gmail.com>> wrote:
ES can befit from `nameof` feature the same way as TS. There is no TS specific 
in it.
It was ask to introduce in TS as a workaround since TS is considered as 
extention of ES.

Case 1. Function guard.
```
function func1(param1, param2, param3, userName, param4, param5) {
   if (userName == undefined) {
   throw new ArgumentNullError(nameof userName); // `ArgumentNullError` is 
a custom error, derived from `Error`, composes error message like "Argument 
cannot be null: userName".
   }
}
```

Case 2. Access extended information an object property.
Assume a function
```
function protoPropertyIsSet(message, property) {
return message != null && message.hasOwnProperty(property);
}
```
Then in code you use it as `if (protoPropertyIsSet(msg, "expiration_utc_time")) 
{... }`.
Having `nameof` would allow you to do that `if (protoPropertyIsSet(msg, nameof 
msg.expiration_utc_time)) {... }`.
You get more robust code.

On Fri, Jun 14, 2019 at 5:46 PM Augusto Moura 
mailto:augusto.borg...@gmail.com>> wrote:
Can you list the benefits of having this operators? Maybe with example use cases

If I understand it correctly, the operator fits better in compiled
(and typed) languages, most of the use cases don't apply to dynamic
Javascript
The only legit use case I can think of is helping refactor tools to
rename properties (but even mismatch errors between strings and
properties names can be caught in compile time using modern
Typescript)

Em sex, 14 de jun de 2019 às 10:05, Stas Berkov
mailto:stas.ber...@gmail.com>> escreveu:
>
> Can we revisit this issue?
>
>
> In C# there is `nameof`, in Swift you can do the same by 

RE: Re: What do you think about a C# 6 like nameof() expression for

2019-06-14 Thread Ron Buckton
A module namespace isn’t an instance of `Module`, it’s a module namespace spec 
object. If it has a `name` member, that is because the module you imported has 
an exported binding called `name`. But what kind of thing it is isn’t what 
matters.

`nameof` just returns a string representation of the static symbolic name of 
its operand. `nameof` would be used at runtime (i.e. during code execution), 
but provides the ability for advanced editors to include it in a “rename” 
refactoring.

The operand merely needs to be an identifier that exists within the current 
lexical scope. `nameof` would not observe TDZ and would not evaluate any 
expression. The ECMAScript static semantics would merely: 1) check that the 
identifier provided to `nameof` is the name of something in the current lexical 
scope, and 2) replace the expression with a string literal representing the 
name.

If `nameof foo.bar` were allowed `nameof` would not actually evaluate 
`foo.bar`, but merely result in `”bar”`. `nameof` does not evaluate anything, 
it is merely a syntactic transformation by the runtime that becomes a string.

Ron

From: guest271314 
Sent: Friday, June 14, 2019 10:07 AM
To: Ron Buckton 
Cc: es-discuss@mozilla.org
Subject: Re: Re: What do you think about a C# 6 like nameof() expression for

Not following the module example. Would not ```ns``` be an instance of 
```Module``` where ```* as ns``` is used?

For the ```class``` example would ```nameof``` be equivalent to 
```Object.getOwnPropertyDescriptors(other).name.value```?

It's not that a language like TypeScript would need this, but rather that users 
of an editor like VS Code or WebStorm that have a JavaScript language service 
would benefit from it.

Is the primary use case a non-simple text editor; e.g., _not_ gedit (GUI) or 
pico or nano (CLI), where the user is depending on the program

for diagnostics (logging and errors)

within a text editor _before_ actually running the code in a given environment 
- not to log errors during code execution?

On Fri, Jun 14, 2019 at 4:29 PM Ron Buckton 
mailto:ron.buck...@microsoft.com>> wrote:
The 'nameof' operator provides the string name of a static symbol (in 
compiler/linker terms, not an ECMAScript 'Symbol'). This is often useful for 
diagnostics (logging and errors), and gives developers a way to reduce 
repetition. It is also extremely helpful in editors that support symbolic 
"rename" refactoring.
While ES functions have a 'name' property, one of the main use cases is to get 
a string representation of the name of a thing that isn't itself reified as an 
object, such as a variable, parameter, or module namespace:
```
import * as ns from "foo";
nameof ns; // "ns"
let fn = function g() {};
fn.name<https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Ffn.name&data=02%7C01%7CRon.Buckton%40microsoft.com%7C104ffaa78f6847e3a31708d6f0eab6e3%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636961288212685352&sdata=sBP1RXbppYfrzbSFUaC%2F80IBZk1tUDqdxeVmbuTveSE%3D&reserved=0>;
 // "g"
nameof fn; // "fn"
```
Here is an example of two common use cases:
```
class C {
  compare(other) {
if (!(other instanceof C)) {
  throw new TypeError(`Invalid argument: ${nameof other} `);
}
  set prop(value) {
this._prop = value;
this.emit("propertychanged", nameof prop);
  }
}
```
It's not that a language like TypeScript would need this, but rather that users 
of an editor like VS Code or WebStorm that have a JavaScript language service 
would benefit from it.
Ron

From: es-discuss 
mailto:es-discuss-boun...@mozilla.org>> on 
behalf of guest271314 mailto:guest271...@gmail.com>>
Sent: Friday, June 14, 2019 9:05:55 AM
To: Stas Berkov
Cc: es-discuss@mozilla.org<mailto:es-discuss@mozilla.org>
Subject: Re: Re: What do you think about a C# 6 like nameof() expression for

Have not tried TypeScript. What are the use cases for JavaScript where 
TypeScript is not used? Does ```nameof()``` check if an object has a specific 
property name defined (```"MutationObserver" in window```; 
```window.MutationObserver```; ```"document" in globalThis```)?

On Fri, Jun 14, 2019 at 1:05 PM Stas Berkov 
mailto:stas.ber...@gmail.com>> wrote:
Can we revisit this issue?

In C# there is `nameof`, in Swift you can do the same by calling
```
let keyPath = \Person.mother.firstName
NSPredicate(format: "%K == %@", keyPath, "Andrew")
```
Let's introduce `nameof` in ES, please.

Devs from TypeScript don't want to introduce this feature in TypeScript unless 
it is available in ES ( https://github.com/microsoft/TypeScript/issues/1579 )
This feature is eagarly being asked by TypeScript community.

I understand there are couple issues related to `nameof` feature in ES. They 
are: minification and what to do if user already ha

Re: Re: What do you think about a C# 6 like nameof() expression for

2019-06-14 Thread Ron Buckton
The 'nameof' operator provides the string name of a static symbol (in 
compiler/linker terms, not an ECMAScript 'Symbol'). This is often useful for 
diagnostics (logging and errors), and gives developers a way to reduce 
repetition. It is also extremely helpful in editors that support symbolic 
"rename" refactoring.

While ES functions have a 'name' property, one of the main use cases is to get 
a string representation of the name of a thing that isn't itself reified as an 
object, such as a variable, parameter, or module namespace:

```
import * as ns from "foo";

nameof ns; // "ns"

let fn = function g() {};
fn.name; // "g"
nameof fn; // "fn"
```

Here is an example of two common use cases:

```
class C {
  compare(other) {
if (!(other instanceof C)) {
  throw new TypeError(`Invalid argument: ${nameof other} `);
}

  set prop(value) {
this._prop = value;
this.emit("propertychanged", nameof prop);
  }
}
```

It's not that a language like TypeScript would need this, but rather that users 
of an editor like VS Code or WebStorm that have a JavaScript language service 
would benefit from it.

Ron

From: es-discuss  on behalf of guest271314 

Sent: Friday, June 14, 2019 9:05:55 AM
To: Stas Berkov
Cc: es-discuss@mozilla.org
Subject: Re: Re: What do you think about a C# 6 like nameof() expression for

Have not tried TypeScript. What are the use cases for JavaScript where 
TypeScript is not used? Does ```nameof()``` check if an object has a specific 
property name defined (```"MutationObserver" in window```; 
```window.MutationObserver```; ```"document" in globalThis```)?

On Fri, Jun 14, 2019 at 1:05 PM Stas Berkov 
mailto:stas.ber...@gmail.com>> wrote:
Can we revisit this issue?

In C# there is `nameof`, in Swift you can do the same by calling
```
let keyPath = \Person.mother.firstName
NSPredicate(format: "%K == %@", keyPath, "Andrew")
```
Let's introduce `nameof` in ES, please.

Devs from TypeScript don't want to introduce this feature in TypeScript unless 
it is available in ES ( 
https://github.com/microsoft/TypeScript/issues/1579
 )
This feature is eagarly being asked by TypeScript community.

I understand there are couple issues related to `nameof` feature in ES. They 
are: minification and what to do if user already has `nameof` function.

Minification.
1. If your code to be minimized be prepared that variable names will also 
change.
2. (just a possibility) Minimizer can have option to replace `nameof(someVar)` 
with result of `nameof` function.

What if user already has `nameof` function.
1. To maintain status quo we can user `nameof` function having priority over 
newly introduced language feature.
2. OR we can use `typeof` syntax, e.g. `nameof msg.userName` (// returns 
"userName" string)
___
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: Duration

2019-03-04 Thread Ron Buckton
Personally, I’d love to see something like this included as part of the 
temporal proposal (https://github.com/tc39/proposal-temporal), as I’ve been 
experimenting with something very much like this here: 
https://github.com/rbuckton/temporal/blob/master/src/Duration.ts.

I think a Duration type that meshes with the proposed `plus` method on temporal 
objects would be a huge benefit.

Ron

From: es-discuss  On Behalf Of Alexandre Morgaut
Sent: Monday, March 4, 2019 10:47 AM
To: es-discuss list 
Subject: Proposal: Duration

Here a proposal to make ECMAScript natively support a Duration Object

I talked about it a long time ago (2011) on the WHATWG mailing list in the 
context of the Timers API: 
https://lists.w3.org/Archives/Public/public-whatwg-archive/2011Feb/0533.htm

l think that such a proposal would better take place in the core of the 
language and having worked on a framework date time APIs I tried to give this 
approach a better look.

ECMAScript natively support Dates since its very first version
It started to support the ISO 8601 string format in edition 5
(15.9.1.15 Date Time String Format )

Durations like Dates can be very tricky, especially with I18n in mind, but the 
ECMA standard already had to be handled most of the Duration tricky part for 
the Date Object in EMCA 262 & ECMA 402.

Duration, sometimes called TimeInterval, is a common concept supported by most 
languages or associated standard libs.

In very short, Duration object would:
- support the ISO syntax in its contructor: new Duration('P6W') // for  Period 
6 Weeks
- allow to handle Date diff operations
- allow to be interpreted by setTimeout() & setInterval()

Please find below a draft exposing the concept
I'd be very happy if someone from TC39 would be interested to champion it
https://github.com/AMorgaut/proposal-Duration

Regards,

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


RE: Proposal: Default object method

2019-01-27 Thread Ron Buckton
There’s nothing in that proposal says that an object with a `Symbol.apply` has 
to have a different `typeof`. It *would* mean that any Call might require 
additional dispatch which could have performance implications. It could also be 
an approach to support “callable” classes:

```js
class Foo {
  constructor() { /* constructor behavior */ }
  static [Symbol.apply]() { /* call behavior */ }
}
```

From: es-discuss  On Behalf Of Jordan Harband
Sent: Sunday, January 27, 2019 9:35 PM
To: Brasten Sager 
Cc: es-discuss 
Subject: Re: Proposal: Default object method

Something that can be invoked has a `[[Call]]` slot, and is `typeof` "function".

Adding a Symbol that makes something callable would have a number of effects - 
it would make `typeof` (one of the most robust operations in the language) 
unsafe, because it would have to access the Symbol method, which could be a 
throwing getter (or even one that just logs how many typeofs are called on it). 
Additionally, it would mean any object could become callable, and any function 
could be made *un* callable.

This seems like a pretty large change, solely to avoid "classes with a single 
method", which arguably should just be a function in the first place.

On Sun, Jan 27, 2019 at 4:05 PM Brasten Sager 
mailto:bras...@brasten.me>> wrote:
Apologies if this has been raised before. I was unable to locate anything 
similar.

Any thoughts or ideas on this proposal would be appreciated!

Original: 
https://gist.github.com/brasten/f87b9bb470973dd5ee9de0760f1c81c7

-Brasten

—

# Proposal: Default object method #

Objects w/ default method can be invoked like a function.

## Problem ##

Objects that are well constrained (single responsibility)
can tend to end up with a single method, or at least a single method
that is important to most consumers. These methods tend to be named
by either verbing the class name (eg. `UserCreator.create()`) or with
some generic `handle` / `perform` / `doTheObviousThing`.

Whatever the name, downstream consumers of the object end up coupled to
two implementation details:

   1) this thing-doer is an object and not a function
   2) this thing-doer's doing method is called `X`

### Example ###

Here we are going to create an object that can be used to
create a user later. Note that downstream consumers will only
care that this object does one thing: create a user. While it
make have other methods eventually for use in some limited
contexts, creating a user is its primary (and often sole-)
responsibility.

```js
class UserCreator {
  constructor(repository) {
this.repository = repository;
  }

  create(name) {
 return this.repository.createUser(name);
  }
}

const userCreator = new UserCreator(userRepository);
```

At this point, the `userCreator` is just a single-method object.
It is useful for injecting into other objects that may need to
create a user. But the fact that the `userCreator` is an object
with a single useful method is an implementation detail to which
consumers become coupled.

```js

// Consumer of `userCreator`. Although this could itself be a
// good example of a "UserCreator"-like object (due to `.handle()`).
//
class UserSignupHandler {
  constructor(userCreator) {
this.userCreator = userCreator;
  }

  handle(userName) {
// UserSignupHandler is aware of ".create" when it really doesn't have to 
be.
//
return this.userCreator.create(userName);
  }
}

const handler = new UserSignupHandler(userCreator);
```

Notably, if we were to change the implementation of UserCreator later to be
a pure function, we would have to change all consumers of UserCreator when
conceptually it shouldn't be needed. There is still a thing-doer that has
the same input/output.


## Proposed Solution ##

An object instance can have a default method. This would allow an
object to be "invoked" exactly like a function, hiding the implementation
detail from consumers.

Note that there are several ways to define how the default method is
determined, and this proposal is less concerned with this aspect than with
what it looks like to invoke the object. We will demonstrate an option here,
but alternatives are welcome.

```js
// This particular implementataion would use a Symbol.
//

class UserCreator {
  constructor(repository) {
this.repository = repository;
  }

  [Symbol.apply](name) {
 return this.repository.createUser(name);
  }
}

const userCreator = new UserCreator(userRepository);

class UserSignupHandler {
  constructor(userCreator) {
// NOTE: at the consumer, it almost makes more sense to
// name these with action verbs, as is done here.
//
this.createUser = userCre

RE: Proposal for faster this assignments in constructor functions

2018-11-28 Thread Ron Buckton
Dart has something like this: 
https://www.dartlang.org/guides/language/language-tour#constructors

```dart
class Point {
  num x, y;

  // Syntactic sugar for setting x and y
  // before the constructor body runs.
  Point(this.x, this.y);
}
```

I could see a form of BindingElement (et al) that allows `this` or `this` `.` 
BindingIdentifier:

```js
class Point {
  constructor(this.x, this.y) {}
}
new Point(10, 20).x; // 10

class Foo {
  constructor(this.x, { y: this.z, …this }) {}
}
const f = new Foo(1, { y: 2, w: 3 });
f.x; // 1
f.z; // 2
f.w; // 3
```

TypeScript has something similar for constructors in the form of “parameter 
property assignments”, but they are triggered by the presence of an modifier 
(i.e. `public`, `private`, `protected`, `readonly`).

Ron

From: es-discuss  On Behalf Of Claude Pache
Sent: Wednesday, November 28, 2018 11:46 AM
To: Simo Costa 
Cc: es-discuss@mozilla.org
Subject: Re: Proposal for faster this assignments in constructor functions


Le 28 nov. 2018 à 19:32, Simo Costa 
mailto:andrysimo1...@gmail.com>> a écrit :

In costructor functions and in the constructor() method in ES6 classes is 
easily to fall in the following pattern:

F(par1, par2, ..., parN) {

  this.par1 = par1;

  this.par2 = par2;

  ...

  this.parN = parN;

}

So my proposal is to avoid those repetitions  by prefixing a dot . to each 
parameter:

F(.par1, .par2, ..., .parN) {}

Simple but quite useful. More info here: 
https://github.com/jfet97/proposal-fast-this-assignments



Simple, but a brand new and nonobvious syntax, for a relatively limited use 
case.

Also, just one dot is too inconspicuous. At the very least, I’d prefer:

```js
function F(this.par1, this.par2, this.par3) { }
```

whose meaning is somewhat more intuitive.


Also noteworthy: in many cases, you can already reduce repetition with the 
combination of `Object.assign`, improved syntax literal, and imagination; see:

http://2ality.com/2014/12/es6-oop.html#use-cases-for-objectassign


—Claude

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


RE: New Proposal: Placeholder syntax

2018-11-28 Thread Ron Buckton
Partial application chose to limit the scope of `?` to argument positions in an 
argument list for a number of reasons. The primary being this case (assuming 
arbitrary expressions were allowed):

```js
let i = 0;
const g = f({ x: i++, y: ? });
```

The goal of partial application was to “fix” non-placeholder arguments at the 
time the partial function result is bound. This means that `i++` above should 
evaluate only once. However, if we allowed placeholders in arbitrary parts of 
an expression, to preserve this behavior we would have to be able to “partially 
fix” any arbitrary expression (such as the property names and property values 
of the object literal above). Various committee members indicated that they 
were very much opposed to this kind of partial fixing.

The other problem with placeholders is scoping. The above example could have 
two interpretations: One where `g` is a partial function for `f` with an 
argument that fills in the `y` property, and one where `f` is called with an 
object that has a property `y` that is an identity function.

A placeholder as an arbitrary expression is also complicated by something like 
`g(f(?))`. If `?` is an arbitrary expression, you need to syntactically mark 
the boundary of the expression, otherwise a user could expect the result to be 
either `x => g(f(x))` or `g(x => f(x))`. In Scala’s case, you end up needing to 
use a block-style for these cases. If `?` is scoped to its immediate argument 
list and does not allow arbitrary expressions, then there becomes only one 
possible interpretation (in this case, `g(x => f(x))`). In this way, partial 
application is like a more powerful syntactic variation of 
Function.prototype.bind, as Function.prototype.bind always fixes arguments in 
the function’s immediate argument list.

Ron

From: es-discuss  On Behalf Of Andrew Kaiser
Sent: Wednesday, November 28, 2018 11:57 AM
To: ljh...@gmail.com
Cc: es-discuss@mozilla.org
Subject: Re: New Proposal: Placeholder syntax

This proposal also works with simple math operations and for accessing fields 
on objects. The partial application lists these expressions as invalid.

```js
// invalid
f(x + ?)  // `?` not in top-level Arguments of call
x + ? // `?` not in top-level Arguments of call
?.f() // `?` not in top-level Arguments of call
```
Admittedly they chose not to include these operations because of the complexity 
it would add to the transpilation, but the placeholder proposal is simpler in 
nature. The partial application proposal alters what is returned by a function 
call, the placeholder proposal replaces an argument inline, and the value a 
called function returns does not change.

On Wed, Nov 28, 2018 at 2:35 PM Jordan Harband 
mailto:ljh...@gmail.com>> wrote:
It seems like the partial application proposal covers all of the use cases of 
yours, at a first glance. What does yours offer that partial application does 
not?

On Wed, Nov 28, 2018 at 11:23 AM Andrew Kaiser 
mailto:kaisea@gmail.com>> wrote:
Do you see a way these proposals can work together? I believe they are solving 
different needs. Both proposals produce a new anonymous function, but partial 
application deals with currying, while the placeholder proposal tries to 
prevent writing a function at all. I can actually see the two working together:

```js
const filenames = ['file1.txt', 'file2.txt' 'output.log' ]
const fileContainsContent = (filename, content) => 
fs.readFileSync(filename).toString().includes(content)

const fileSearchers = filenames.map(fileContainsContent(*, ?))
const filesContainingSearch = fileSearchers.filter(searcher => 
searcher('foobar'))
```

This isn't a very useful example, but you can see how the proposals differ 
accomplish different things

On Wed, Nov 28, 2018 at 1:30 PM Jordan Harband 
mailto:ljh...@gmail.com>> wrote:
You may be interested in the partial application proposal: 
https://github.com/tc39/proposal-partial-application

On Wed, Nov 28, 2018 at 10:17 AM Andrew Kaiser 
mailto:kaisea@gmail.com>> wrote:
Hi all,

I have created a short proposal to introduce syntactic sugar for anonymous 
functions in a 'scala-like' manner, linked here 
https://github.com/andykais/proposal-placeholder-syntax.

I am hoping to hear feedback on whether or not this is interesting to people, 
as well as feedback 

RE: Arrow methods

2018-11-18 Thread Ron Buckton
C# has a similar syntax for shorthand expression bodies 
(https://github.com/dotnet/roslyn/wiki/New-Language-Features-in-C%23-6#expression-bodies-on-method-like-members):

```cs
class Point {
  private int x;
  private int y;

  …

  // expression bodied getters (read-only)
  public int X => x;
  public int Y => y;

  // expression bodied method
  public Point Move(int dx, int dy) => new Point(x + dx, y + dy);
}
```

From: es-discuss  On Behalf Of T.J. Crowder
Sent: Sunday, November 18, 2018 6:31 AM
To: Sultan 
Cc: es-discuss@mozilla.org
Subject: Re: Arrow methods

On Fri, Nov 16, 2018 at 8:42 PM Sultan
mailto:thysul...@gmail.com>> wrote:
> It has an added reach in usefulness when you consider nested
> classes:
>
> class A {
>   foo() {
> return class B {
>   bar() => {
> return this // refers to instance A
>   }
> }
>   }
> }
>
> This is not possible today without creating a self-like variable
> for bar to reference A's instance; Which is one of the points
> arrow functions addressed.

It is, just not within the `class` construct:

```js
class A {
  foo() {
class B {
}
B.prototype.bar = () => {
  return this; // refers to instance A
};
return B;
  }
}
```

I agree with Tab Atkins Jr.: In your nested classes example, I'd expect `this` 
within `bar` to be the `B` instance, not the `A` instance. I think the more 
natural definition of that syntax (if it were adopted) would be a prototype 
function that is effectively auto-bound to the instance at construction time, 
like this common pattern today:

```js
class B {
  constructor() {
this.bar = this.bar.bind(this);
  }
  bar() {
return this;
  }
}
```

In fact I could see some benefit to that syntax, since people use class fields 
for that use-case which can make mocking difficult.

But I'm not keen on that syntax with the semantics you're proposing.

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


RE: Array.prototype.remove(item)

2018-10-10 Thread Ron Buckton
That depends entirely on what the return value means. Returning Boolean from 
`add` doesn’t mean, “does the value now exist in the set”, but rather means 
“was the set modified as a result of this operation”.

To avoid any possible performance cost for calling `has` before `add`, I 
usually have to do something like:

```
function setAdd(set, value) {
  const size = set.size;
  set.add(value);
  return size !== set.size;
}
```

From: es-discuss  On Behalf Of Jordan Harband
Sent: Wednesday, October 10, 2018 7:19 PM
To: jollee...@outlook.com
Cc: es-discuss 
Subject: Re: Array.prototype.remove(item)

Man: `add` doesn't need to return a boolean, because it always results in the 
item being in the collection after the fact. You could subclass Set, and make 
`.add` do that, though, if you like! Alternatively, you could use `.has` prior 
to calling `.add`, to get your boolean value.

On Wed, Oct 10, 2018 at 1:01 AM Man Hoang 
mailto:jollee...@outlook.com>> wrote:
The problem with `Set` is that its `add` method returns `this` instead of 
`boolean`. If `Set.prototype.add` returned `boolean`, I would have used `Set`.

That’s why in the `select` method of my sample code, I use a custom defined 
method named `pushIfAbsent`. The actual type of `_values` is not `Array` but a 
subclass of `Array`.
``` js
export class MyArray extends Array {
/**
 * Adds [item] to the end of this array if it's not already in this array.
 *
 * Returns `true` is [item] was added, `false` otherwise.
 */
pushIfAbsent(item: E): boolean {
if (!this.includes(item)) {
this.push(item);
return true;
}
return false;
}

/**
 * Removes the first occurrence of [item] from this array.
 *
 * Returns `true` if [item] was in this array, `false` otherwise.
 */
remove(item: E): boolean {
const i = this.indexOf(item);
if (i >= 0) {
this.splice(i, 1);
return true;
}
return false;
}
}
```
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Proposal: Add Map.prototype.putIfAbsent

2018-10-10 Thread Ron Buckton
I have seen this in other languages as `getOrCreate(key, valueFactory)`. 
Dictionaries in .NET have a `TryGetValue(key, out value)` method that returns a 
boolean and has an ‘out’ parameter used to assign the value if it exists. The 
performance issue regarding keys is one of my common concerns with 
`Set.prototype.add`, as it would have been significantly more useful for `add` 
to return a Boolean indicating whether the value was added (true), or was 
already present (false).

At the end of the day, I usually just end up defining `mapGetOrCreate(map, key, 
valueFactory)` and `setAdd(set, value)` utility functions that I end up using.

From: es-discuss  On Behalf Of Andrea Giammarchi
Sent: Wednesday, October 10, 2018 9:30 PM
To: Jordan Harband 
Cc: es-discuss@mozilla.org
Subject: Re: Proposal: Add Map.prototype.putIfAbsent

No. The raised concern has been common among developers and the main issue is 
that `set` returns itself which is the least useful pattern.

Your suggestion would make sense if `const value = map.has(key) ? map.get(key) 
: map.set(key, createValue())` instead ES went for chain ability and yet, to 
date, I have to see a single usage of `map.set(a, 1).set(b, 2)` in the wild.

On top of that, needing to `.has` and then `.get` is a performance shenanigan 
many would likely avoid at all costs 'cause AFAIK in no engine `.has(key)` 
temporarily retains last searched key to boost up the immediate `.get(key)` 
later on so having a `.putIfAbsent(key, createValue())` that returns either the 
found or the created value is a clear win.



On Thu, Oct 11, 2018 at 6:20 AM Jordan Harband 
mailto:ljh...@gmail.com>> wrote:
Thanks, your correction explains what the benefit would be (the awkward need to 
cache the value). However this seems simpler to me: `if (!map.has(key)) { 
map.set(key, getValue()); } const value = map.get(key);`

On Wed, Oct 10, 2018 at 9:07 PM Isiah Meadows 
mailto:isiahmead...@gmail.com>> wrote:
I presume you mean this?

```js
// Proposed
map.putIfAbsent(key, init)

// How you do it now
let value
if (map.has(key)) {
value = map.get(key)
} else {
map.set(key, value = init())
}
```

BTW, I'd like to see this make it myself, just slightly different:

- How you call it: `map.getOrPut(key, init, thisValue=undefined)`
- How `init` is called: `init.call(thisValue, key, map)`

This pattern is incredibly common for caching. It'd be nice if I didn't have to 
repeat myself so much with it. I would be more willing to stuff it in a utility 
function if it weren't for the fact the use cases often entail 
performance-sensitive paths, and engines aren't reliable enough in my 
experience with inlining closures passed to non-builtins.

On Wed, Oct 10, 2018 at 22:54 Jordan Harband 
mailto:ljh...@gmail.com>> wrote:
It seems like your proposed `const value = map.putIfAbsent(key, 
getExpensiveValue);` is achievable already with `const value = map.has(key) ? 
map.get(key) : map.set(getExpensiveValue());` - am I understanding your 
suggestion correctly?

On Wed, Oct 10, 2018 at 12:46 AM Man Hoang 
mailto:jollee...@outlook.com>> wrote:
Consider the following function
``` js
/**
* Parses the locale sensitive string [value] into a number.
*/
export function parseNumber(
value: string,
locale: string = navigator.language
): number {
let decimalSeparator = decimalSeparators.get(locale);
if (!decimalSeparator) {
decimalSeparator = Intl.NumberFormat(locale).format(1.1)[1];
decimalSeparators.set(locale, decimalSeparator);
}

let cleanRegExp = regExps.get(decimalSeparator);
if (!cleanRegExp) {
cleanRegExp = new RegExp(`[^-+0-9${decimalSeparator}]`, 'g');
regExps.set(decimalSeparator, cleanRegExp);
}

value = value
.replace(cleanRegExp, '')
.replace(decimalSeparator, '.');

return parseFloat(value);
}

const decimalSeparators = new Map();
const regExps = new Map();
```

This function can be simplified quite a bit as follows
``` js
export function parseNumber(
value: string,
locale: string = navigator.language
): number {
const decimalSeparator = decimalSeparators.putIfAbsent(
locale, () => Intl.NumberFormat(locale).format(1.1)[1]);

const cleanRegExp = regExps.putIfAbsent(
decimalSeparator, () => new RegExp(`[^-+0-9${decimalSeparator}]`, 'g'));

value = value
.replace(cleanRegExp, '')
.replace(decimalSeparator, '.');

return parseFloat(value);
}
```
if `Map` has the following instance method
``` js
export class Map {
/**
 * Look up the value of [key], or add a new value if it isn't there.
 *
 * Returns the value associated to [key], if there is one.
 * Otherwise calls [ifAbsent] to get a new value, associates [key] to
 * that value, and then returns the new value.
 */
putIfAbsent(key: K, ifAbsent: () => V): V {
let v = this.get(key);
if (v === undefined) {
v = ifAbsent();
this.set(key, v);
  

RE: Pointers

2018-03-19 Thread Ron Buckton
> -Original Message-
> From: Pier Bover 
> Sent: Monday, March 19, 2018 5:06 PM
> To: Isiah Meadows 
> Cc: Ron Buckton ; es-discuss  disc...@mozilla.org>
> Subject: Re: Pointers
> 
> So the proposal is basically having references to primitives like strings, 
> bools,
> etc?

If you are talking about my proposal, then no. References wouldn't be limited 
to primitives, for example:

```js
function tryGet(map, key, ref value) {
  if (map.has(key)) {
value = map.get(key);
return true;
  }
  value = undefined;
  return false;
}

const map = new Map();
map.set("a", { x: 1 });
let value;
console.log(tryGet(map, "a", ref value), value); // true { x: 1 }
console.log(tryGet(map, "b", ref value), value); // false undefined
```

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


RE: Pointers

2018-03-19 Thread Ron Buckton
> -Original Message-
> From: es-discuss  On Behalf Of Isiah
> Meadows
> Sent: Monday, March 19, 2018 3:21 PM
> To: Michael J. Ryan 
> Cc: es-discuss 
> Subject: Re: Pointers
> 
> And even if we *could* get pointers into JS, I'd *strongly* not want it to be
> like what's proposed here. Instead, I'd prefer an object encapsulating a
> reference to a variable, something like this (although engines could avoid the
> ceremony of closures here):
> 
> ```js
> let foo = 1;
> 
> func(ref foo, bar)
> // Equivalent to:
> func({deref: () => foo, set: v => foo = v}, bar)
> 
> function func(ref foo, bar) {
> foo += 2
> }
> 
> // Equivalent to:
> function func(foo) {
> foo.set(foo.deref() + 2)
> }
> ```

I put together a strawman for this last year at 
https://github.com/rbuckton/proposal-refs, but I haven't had much time to work 
on it. 

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


RE: Picking (deconstructing) properties into object literals

2017-08-22 Thread Ron Buckton
As a alternative, consider 
https://github.com/rbuckton/proposal-shorthand-improvements.

From: kai zhu
Sent: Tuesday, August 22, 2017 9:45 PM
To: Isiah Meadows
Cc: es-discuss@mozilla.org
Subject: Re: Picking (deconstructing) properties into object literals

-1 and agree with isiah

furthermore, i see javascript deconstruction as a never-ending can-of-worms 
that too-often devolves into ruby-esque confusion / arguments over the “best” 
way to do assignments. NO AMOUNT of language-spec changes will resolve all 
these arguments, so forget about it.

p.s. the principle of avoiding language-spec changes that snowball into 
necessitating future language-spec changes, when established good-enough 
solutions already exist, should be used more often by tc39 (and also avoid 
needlessly de-optimizing engine-implementations and making the overall 
world-wide-web slower).

On Aug 23, 2017, at 12:36 PM, Isiah Meadows 
mailto:isiahmead...@gmail.com>> wrote:

Honestly, I'm not sure how necessary this really is. `_.pick` exists
in Lodash, Underscore, and Ramda, but I'm not seeing it in persistent
data structure libraries like Immutable.js [1] or Mori [2], where it
would seemingly be *more* critical.

[1]: 
https://facebook.github.io/immutable-js/docs/#/Map
[2]: 
https://swannodette.github.io/mori/

For what it's worth, with those libraries, if you'd want something
like `pick`, you could use something like this:

```js
// Immutable.js
function pick(map, keys) {
   return map.filter((_, key) => keys.includes(key))
}

// Mori
function pick(map, ...keys) {
   return mori.reduce(
   (acc, key) => mori.assoc(acc, key, mori.get(map, key)),
   mori.hashMap(), keys)
}
```
-

Isiah Meadows
m...@isiahmeadows.com

Looking for web consulting? Or a new website?
Send me an email and we can get started.
www.isiahmeadows.com


On Tue, Aug 22, 2017 at 11:22 PM, Bob Myers  wrote:
Extending the ways we can construct object literals has been a sort of theme
in JS language design recently, with shorthand object notation in ES6, and
now spread properties. The motivations include conciseness and readability.

With destructuring assignment, the community decided it made sense to add
syntax to easily destructure selected properties of an object into
variables. With spread properties, the community is deciding it makes sense
to add syntax to easily include all properties from one object into an
object literal. The missing piece is the ability to include selected
properties of an object into an object literal.

When asked by people we are mentoring or teaching how to create an object
containing selected properties from other objects (which happens with
surprising frequency), we usually just tell them to write

```js
{p: a.p, q: a.q, r: b.r, s: b.s}
```

Or sometimes

```js
const {p, q} = a;
const {r, s} = b;
const newObj = {p, q, r, s};
```

Neither of which is ideal. In this proposal, we allow the following syntax:

```js
{ {p, q} = a, {r, s} = b }
```

Here, the `{p, q} = a` is exactly the same production as the spec's
*AssignmentExpression**, as used in destructuring assignment. That includes
the ability to rename properties (`{q1: q2} = a}`), specify defaults (`{q1 =
42} = a`), and pick out nested properties (`{q1: {q11}} = a`). In other
words, we take full advantage of the power of current destructuring
assignment syntax when picking properties into object literals. The sole new
syntactic aspect in this proposal is the ability to place the
*AssignmentExpression* construct *inside* an object literal.

A fuller description of this proposal can be found at
https://github.com/rtm/js-pick-notation.

--
Bob


___
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: Stream + async await

2017-07-29 Thread Ron Buckton
One option might be something like 
https://github.com/rbuckton/prex/blob/master/docs/scheduling.md#class-asyncqueue.
 It allows you to put items on the queue as soon as they are available.

Ron

From: Naveen Chawla
Sent: Saturday, July 29, 2017 3:54 AM
To: Domenic Denicola; 
es-discuss@mozilla.org
Subject: Re: Stream + async await

Interesting!!!

Excuse my ignorance, but with this construct, how would you trivially invoke a 
"publish" ahead of any given "consumption"?

As far as I can see,

```
for await (const item of requestItems){

}
```
on its own is purely a "front-pressure" construct. That is, each request is 
made upon the completion and satisfactory consumption of the last one.

Can you suggest a way to trivially invoke some "back pressure" using this 
construct? By this I mean - invoke extra requests before they come to be 
consumed (like you can do with reactive streaming libraries). An example use 
would be if you wanted to do some "eager loading" of data while the user is 
likely to be viewing but not currently interacting with existing content, for 
example.

You seem very familiar with this construct, so I wouldn't be surprised if 
you've already thought about this! (If you're too busy I'm sure there are 
others here familiar with it too!)

On Tue, 11 Jul 2017 at 21:09 Domenic Denicola 
mailto:d...@domenic.me>> wrote:
https://github.com/tc39/proposal-async-iteration

From: es-discuss 
[mailto:es-discuss-boun...@mozilla.org] 
On Behalf Of Naveen Chawla
Sent: Tuesday, July 11, 2017 09:24
To: es-discuss@mozilla.org
Subject: Stream + async await

It'd be great to have async stream constructs such as: 
http://reactivex.io/rxjs/
 , supported natively, such that they can be used directly with the async / 
await keywords for async stream programming in a linear fashion (analogous to 
what can already be done with linearly awaiting Promises, but for async streams 
instead).
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Re: Functional Operators

2017-07-16 Thread Ron Buckton
(apologies for top posting as I’m replying from my phone)

Functional operators are not very interesting on their own, but are much more 
interesting in terms of pipelines and partial application. However, they may be 
a stretch in either scenario, so I’m not expecting them to be part of any 
official proposal for pipeline/partial application at this time.

By ergonomic, I meant that ‘{+}’ is far fewer characters than ‘Math.add’. Also, 
not every ‘+’ is arithmetic (i.e. string concatenation).

I can imagine a world where I can do:

```js
const sum = numbers |> reduce(?, {+});
const joined = strings |> reduce(?, {+});
```

As a shorthand for:

```js
const sum = numbers |> reduce(?, (a, b) => a + b);
const joined = strings |> reduce(?, (a, b) => a + b);
```

(I’m using `|>` here for pipeline and `?` as a positional argument for partial 
application here)

Ron

From: Darien Valentine<mailto:valentin...@gmail.com>
Sent: Sunday, July 16, 2017 1:18 AM
To: es-discuss@mozilla.org<mailto:es-discuss@mozilla.org>
Subject: Re: Re: Functional Operators

If I understand right, Ron, it means a new RHS for PrimaryExpression and would 
behave like a reference, except that it is (presumably) not a valid assignment 
target? Can you explain more about the ergonomics — maybe it’s just from lack 
of familiarity, but to me this seems pretty grawlixy, like something you’d see 
in Perl.

In other words, I’m unsure how `arr.reduce({+})` is more ergonomic than 
`arr.reduce(Math.add)`\*. Assuming it is and I’m just failing to see it, is the 
benefit significant enough to merit new syntax?

(On further consideration, maybe `Reflect.add`, since `+` is not specific to 
numeric values...)

On Sun, Jul 16, 2017 at 2:19 AM, Ron Buckton 
mailto:ron.buck...@microsoft.com>> wrote:
I have been looking into functional operators while working on a proposal for 
pipeline and partial application. I’ve found that a sigil like `{+}` is just as 
ergonomic as `(+)`, but has fewer lookahead issues with respect to regular 
expression parsing. While `(/)` is ambiguous as to whether it would be a 
division function or the start of a parenthesized regular expression literal, 
`{/` is far less ambiguous in most expression positions. The only ambiguity is 
at the statement level where `{/` could be interpreted as the start of a block 
with a regular expression literal. However, it is fairly unlikely this 
expression would be used in this position, and this can be mitigated using 
parentheses just as we do for object assignment patterns in destructuring 
assignments.

The other ambiguous case is how to differentiate between overloaded binary and 
unary operators. For that, I’ve considered following the approach taken by F# 
and prefixing overloaded unary operators with tilde. As such `{+}` would always 
be a binary plus function, while `{~+}` would be the unary plus function. In 
the same vein, `{-}` would be binary minus, while `{~-}` would be the unary 
minus function. For non-overloaded unary operators the prefix is unnecessary, 
so `{~}` and `{!}` would not be prefixed.

While built-ins could serve this case, they are far less ergonomic than a 
shorthand sigil for an operator. On the other hand, we could have both, with 
the operator sigils acting as shorthand for the long-form built-in methods. 
Either way, I would expect `{+} === {+}` as there is no sense in allocating a 
fresh function object each time it is encountered. Ideally, these would be 
frozen functions that are created once per realm and have the same semantics as 
an arrow function (i.e. [[Call]] but no [[Construct]], etc.).

Ron

From: es-discuss 
[mailto:es-discuss-boun...@mozilla.org<mailto:es-discuss-boun...@mozilla.org>] 
On Behalf Of Darien Valentine
Sent: Monday, July 10, 2017 3:08 PM
To: es-discuss@mozilla.org<mailto:es-discuss@mozilla.org>
Subject: Re: Re: Functional Operators

Minor point regarding the syntax given here: introducing `(/)` would likely be 
problematic because it breaks the constraint that there are no positions in the 
grammar where both a division operator and a regular expression literal could 
be valid continuations.

(Perhaps new built-ins like `Math.add` etc might represent a more consistent 
approach to the issue of operators not being function references?)

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


RE: Re: Functional Operators

2017-07-15 Thread Ron Buckton
I have been looking into functional operators while working on a proposal for 
pipeline and partial application. I’ve found that a sigil like `{+}` is just as 
ergonomic as `(+)`, but has fewer lookahead issues with respect to regular 
expression parsing. While `(/)` is ambiguous as to whether it would be a 
division function or the start of a parenthesized regular expression literal, 
`{/` is far less ambiguous in most expression positions. The only ambiguity is 
at the statement level where `{/` could be interpreted as the start of a block 
with a regular expression literal. However, it is fairly unlikely this 
expression would be used in this position, and this can be mitigated using 
parentheses just as we do for object assignment patterns in destructuring 
assignments.

The other ambiguous case is how to differentiate between overloaded binary and 
unary operators. For that, I’ve considered following the approach taken by F# 
and prefixing overloaded unary operators with tilde. As such `{+}` would always 
be a binary plus function, while `{~+}` would be the unary plus function. In 
the same vein, `{-}` would be binary minus, while `{~-}` would be the unary 
minus function. For non-overloaded unary operators the prefix is unnecessary, 
so `{~}` and `{!}` would not be prefixed.

While built-ins could serve this case, they are far less ergonomic than a 
shorthand sigil for an operator. On the other hand, we could have both, with 
the operator sigils acting as shorthand for the long-form built-in methods. 
Either way, I would expect `{+} === {+}` as there is no sense in allocating a 
fresh function object each time it is encountered. Ideally, these would be 
frozen functions that are created once per realm and have the same semantics as 
an arrow function (i.e. [[Call]] but no [[Construct]], etc.).

Ron

From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Darien 
Valentine
Sent: Monday, July 10, 2017 3:08 PM
To: es-discuss@mozilla.org
Subject: Re: Re: Functional Operators

Minor point regarding the syntax given here: introducing `(/)` would likely be 
problematic because it breaks the constraint that there are no positions in the 
grammar where both a division operator and a regular expression literal could 
be valid continuations.

(Perhaps new built-ins like `Math.add` etc might represent a more consistent 
approach to the issue of operators not being function references?)
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Allowing object field name shorthand

2017-06-25 Thread Ron Buckton
There is one place where I could see this syntax being useful, though with 
different semantics, is a feature from C# that I seen used to good effect: 
Dotted names for shorthand property assignments.

For example:

```
const results = books.map(x => ({
  x.isbn,
  x.title,
  x.category.categoryName
}));

// creates: [{ isbn: 123456789, title: “…”, categoryName: “…” }, …]
```

In this example, the actual name for the property is the rightmost identifier 
of the expression. This differs from the proposal at the start of this thread, 
but may also be worth considering.

Ron

(My apologies for formatting as I wrote this up on my phone)

From: Mark
Sent: Sunday, June 25, 2017 10:09 AM
To: Michael Kriegel; 
es-discuss@mozilla.org
Subject: Re: Allowing object field name shorthand


Another -1 for this.

It adds complexity to object initializer processing, both in the obvious way 
(has to figure out to create the hidden object or possibly several nested 
hidden objects), and around the fact that object initializers are processed in 
source code order.

Exactly, this proposal assumes nested objects and that the nested key is 
referencing that object. But to assume this is problematic. What if the user 
wants the nested value to be something other than a plain object? with this 
approach, they’re stuck with just creating native objects.

Not that it isn’t a good idea, but I think the negative effects of this change 
outweigh the benefit.

​


On Fri, Jun 23, 2017 at 1:27 AM Michael Kriegel 
mailto:michael.krie...@actifsource.com>> wrote:

I also vote against this. A further problem could be duplication of field names 
in large objects. Imagine there is a field2.field3.field4.field5 in the 
beginning of your object and then another one 100 lines below. Using the 
currently well defined way to define nested objects at least groups fields 
which belong to an object.

var obj = {
field1: "val" ,
field2.field3: 3,
//hundrets of lines
field2.field3: true
};

Also it is much shorter, not to repeat the field names each time:


var obj = {
field1: "val" ,
field2:{
  field3: 3,
  field4: true
}
};

Michael

On 23.06.2017 04:13, Sebastian Malton wrote:

I don't see how this is like referencing the object a field is in during object 
construction. Yes field2.field4 would not be able to reference field2.field3 
but that is not what I am proposing. I am proposing a syntactic sugar for 
nested objects

On 2017-06-22 10:05 PM, J Decker wrote:


On Thu, Jun 22, 2017 at 7:56 AM, Sebastian Malton 
mailto:sebast...@malton.name>> wrote:
I would like to propose that the dot or '.' is allowed in object field names so 
that the following are allowed.

var obj = {
field1: "val" ,
field2.field3: 3,
field2.field4: true
};


This is much like
var obj = {
   field1: 3
   field2 : 4
   field3 : obj.field2+3
}

which falls apart because obj isn't technically fully defined, and doesn't have 
a field2.  So your second field2.field4 wouldn't be able to reference the 
previous object created for field2.field3.

it would be a huge complexity for engines to create objects



Sebastian


___
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



--
Michael Kriegel • Head of R&D • Actifsource AG • Haldenstrasse 1 • CH-6340 Baar 
• 
www.actifsource.com

RE: Array pointer getter?

2017-06-02 Thread Ron Buckton
I recently put together https://github.com/rbuckton/ecmascript-ref which is 
somewhat similar to this.

From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Alex 
Falcon
Sent: Friday, June 2, 2017 9:06 AM
To: es-discuss@mozilla.org
Subject: Array pointer getter?

Hello. I heard about SIMD, Atomics, etc. and they accept as first arguments 
"array, index", so because ES6 have spreads, I suggest to make next things:

let array = [0, 2, 3];
let ptr = array{0}; // don't get value, but pair of [array, 0], also this is 
proxied which you have setter and getter "value"
let ptr = array.ptr(0); // alternate, functional

ptr.value = 1; // setter
let acceptance = ptr.value; // getter

// also you can just use these pointers without extra indexing
let idx = Atomics.add(...ptr, 1);

It should available for both: typed and regular arrays.

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


RE: throwif operator

2017-04-11 Thread Ron Buckton
I’d much rather see something more like C# 7’s throw expressions: 
https://docs.microsoft.com/en-us/dotnet/articles/csharp/whats-new/csharp-7#throw-expressions

```js
// original example
fs.writeFile("message.txt", "Hello Node.js", err => err ? throw err : 
console.log("The file has been saved.");

// better example
function choose(kind) {
  return kind === 0 ? choseZero() : kind === 1 ? chooseOne() : throw new 
Error("out of range");
}
```

Ron

From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of T.J. 
Crowder
Sent: Tuesday, April 11, 2017 5:20 AM
To: Elie Rotenberg 
Cc: Нурбек ; es-discuss 
Subject: Re: throwif operator

I don't think we need a new keyword for this, both because of Elie's point 
about handling it with a `throwif` function, and because Node's callback 
pattern is a bit old-fashioned in the world of promises and async/await. Until 
the Node API is updated to support promises natively, you can use one of the 
various "promisifying" libs to promisify the API:

```js
const pfs = /*...promisified version of fs*/;
```

...and then:

```js
pfs.writeFile("message.txt", "Hello Node.js")
.then(() => console.log("The file has been saved."));
```

...and like your original code snippet, it will (on recent versions) terminate 
Node if you don't handle the error.

Combined with `async`/`await`, it becomes even cleaner:

```js
await pfs.writeFile("message.txt", "Hello Node.js");
console.log("The file has been saved.");
```

(Of course, that has to be within an `async` function.)

-- T.J. Crowder

On Tue, Apr 11, 2017 at 1:15 PM, Elie Rotenberg 
mailto:e...@rotenberg.io>> wrote:
const throwIf = (fn) => (err, ...args) => {
  if(err) throw err;
  return fn(...args);
};

...

fs.writeFile('message.txt', 'Hello Node.js', throwIf(() => console.log('The 
file has been saved')));


No need to extend the language and preempt keywords with stuff you can very 
easily implement in userland.
I'm not even convinced such a construct would be a good idea anyway to 
encourage rethrowing errors without thinking if it can be handled locally.

On Tue, Apr 11, 2017 at 2:06 PM, Нурбек 
mailto:nurbek...@gmail.com>> wrote:
An example from node.js documentation:

fs.writeFile('message.txt', 'Hello Node.js', (err) => {
  if (err) throw err;
  console.log('The file has been saved!');
});

This looks like a common way to handle errors when the first parameter is an 
instance of Error.

Yes, this line of code is short and easy to copy-paste.
But introducing something like this:

fs.writeFile('message.txt', 'Hello Node.js', (err) => {
  throwif err;
  console.log('The file has been saved!');
});

would make the code much cleaner and bring some sort of standart way to handle 
such errors.

___
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: Resource management

2016-12-31 Thread Ron Buckton
> -Original Message-
> From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Isiah
> Meadows
> Sent: Saturday, December 31, 2016 8:34 AM
> To: J Decker 
> Cc: Raul-Sebastian Mihăilă ; es-discuss  disc...@mozilla.org>
> Subject: Re: Resource management
> 
> Not enough. Not looking for an `await` replacement, but something closer to
> Python's `with` statement or Java's `try`-with-resources.
> Or, if you want something
> 
> Python:
> https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fpreshin
> g.com%2F20110920%2Fthe-python-with-statement-by-
> example%2F&data=02%7C01%7Cron.buckton%40microsoft.com%7C9767f9fc
> 4f8a4e3489b608d4319ad95d%7C72f988bf86f141af91ab2d7cd011db47%7C1%7
> C0%7C636187988525799540&sdata=BbbqX753QBWZaGwXqqmdWbX7sOvdp
> 3VADi%2FLjqpf2%2Fs%3D&reserved=0
> Java:
> https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdocs.o
> racle.com%2Fjavase%2Ftutorial%2Fessential%2Fexceptions%2FtryResourceC
> lose.html&data=02%7C01%7Cron.buckton%40microsoft.com%7C9767f9fc4f8
> a4e3489b608d4319ad95d%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0
> %7C636187988525799540&sdata=wVj3VjrOri80tOmnK%2Bvyoe2e7rb2Ft%2B
> wHv%2BkjOk%2FsFQ%3D&reserved=0
> 
> JavaScript's idioms tend towards Python, Java, C#, etc. in how resources are
> handled, so things like Ruby's `begin`-`ensure` wouldn't work as well (that
> was where I got my generator workaround from, actually, and as you can
> see, it's not exactly very obvious).
> -
> 
> Isiah Meadows
> m...@isiahmeadows.com

Speaking of C#, the C# variant of this is the `using` statement: 
https://msdn.microsoft.com/en-us/library/yh598w02.aspx

I'm not advocating `using` as a new keyword for ES, given it's not already 
reserved and would have ASI hazards. The Java "try-with-resources" seems to be 
a fairly flexible syntax, though its adoption in ES would be predicated on some 
well-defined heuristic for determining which method to be used, given that ES 
does not have interfaces (and thus no System.IDisposable or 
java.lang.AutoCloseable). That would likely be an existing method name, such as 
"return" as used in iterators today, or a built-in Symbol which could be 
retrofit onto %IteratorPrototype%.

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


RE: expanding comments proposal

2016-10-21 Thread Ron Buckton
> From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Gert
> Cuykens
> Sent: Friday, October 21, 2016 4:56 PM
> To: Tab Atkins Jr. 
> Cc: Bruno Jouhier ; es-discuss  disc...@mozilla.org>
> Subject: Re: expanding comments proposal
> 
> There are two reasons for that, one is am not a typescript expert but if you
> want the complete typescript syntax set I can look it up and try to summarize
> the complete syntax and find some typescript expert who can help me on
> this. Two I dont want to exclude other languages that I dont know off and
> make them feel like they don't count. But I admit my end goal for me
> personally is indeed aimed to typescript because I use it the most.

If this is aimed at the fact that you would like to be able to paste TypeScript 
code into JSBin, please be aware that JSBin does have support for TypeScript: 
http://jsbin.com/xeticulini/edit?html,js

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


RE: Promises as Cancelation Tokens

2016-01-04 Thread Ron Buckton

This gist contains the 
TypeScript declarations for the version of CancellationToken I’ve been using 
for a number of small projects. The basic API shape is:

```ts
class CancellationTokenSource {
  constructor(linkedTokens?: CancellationToken[]);
  token: CancellationToken;
  cancel(reason?: any): void;
  close(): void;
}
class CancellationToken {
  static none: CancellationToken;
  canBeCanceled: boolean;
  canceled: boolean;
  reason: any;
  throwIfCanceled(reason?: any): void;
  register(callback: (reason?: any) => void): CancellationTokenRegistration;
}
interface CancellationTokenRegistration {
  unregister(): void;
}
```

The approach I use has the following considerations:


•   The responsibility for cancellation is split between two types:

o   CancellationTokenSource – This type is responsible for propagating a 
cancellation signal and linking multiple tokens together (useful to cancel a 
graph of async operations, such as cancelling all pending fetch request).

o   CancellationToken – A read-only sink for a cancellation signal. 
Asynchronous operations can either synchronously observe whether the 
cancellation signal has been set, or register an callback for asynchronous 
notification of a cancellation signal.

•   Once a callback has been registered for asynchronous notification of a 
cancellation signal, it can later be unregistered.

•   Asynchronous notifications are queued and handled at a higher priority 
than Promise continuations.

•   The reason for cancellation can be explicitly supplied. If not 
supplied, the reason would be a generic “The operation was canceled” error.

Splitting a cancellation signal across two classes has several benefits. One 
benefit is that it allows the producer of a cancellation signal to limit access 
to the ability to initiate that signal. This is important if you wish to have a 
single shared cancellation source for multiple concurrent asynchronous 
operations, but need to hand off a cancellation token to a third party without 
worrying that the third party code would unintentionally cancel operations that 
it does not itself own. Another benefit is the ability to create more complex 
cancellation graphs through linking multiple cancellation tokens.

I agree with Domenic that it is necessary to be able to synchronously observe 
the canceled state of a cancellation token, and that it is also necessary to be 
able to observe a cancellation signal asynchronously. However, I have found 
that the asynchronous notification needs to be triggered at a higher priority 
than Promise “then” tasks. Consider the following, albeit contrived, example:

```js
let source = new CancellationTokenSource();
let p = new Promise((resolve, reject) => {
  Promise.resolve(1).then(resolve);
  source.token.register(reject);
  source.cancel();
});
```

Since “source.cancel()” is executed synchronously, one would expect that `p` 
would be rejected. If the notification were merely added to the same micro-task 
queue as Promise “then” tasks, `p` would be resolved first. By making the 
micro-task queue into a priority queue, we can allow cancellation notifications 
to be processed at a higher priority while still keeping the API itself 
asynchronous. In .NET, cancellation notifications are executed synchronously, 
however this conflicts with the intent to ensure an asynchronous API is 
consistently asynchronous.

This approach also allows cancellation tokens to be more general-purpose. By 
not directly tying cancellation into Promises, they can be used with other 
future asynchronous primitives such as Observables, async generators, etc.

Ron

From: Kevin Smith
Sent: Monday, January 4, 2016 11:44 AM
To: Tab Atkins Jr.; Domenic 
Denicola
Cc: es-discuss
Subject: Re: Promises as Cancelation Tokens

The best approach in cases like this is to avoid the word altogether.
The fact that there's confusion at all means people will mess it up
and get annoyed, even if there's a "winner" in overall usage.

Hmmm...  Maybe

class CancelToken {
  constructor(init);
  get cancelRequested() : bool;
  whenCancelRequested(callback) : void;
}

Or more/overly tersely:

class CancelToken {
  constructor(init);
  get requested() : bool;
  whenRequested(callback) : void;
}




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


RE: Re: Propose simpler string constant

2015-12-16 Thread Ron Buckton
In C#, an enum is a declaration that defines a distinct type consisting of a 
set of named constant values of that type. The distinct type of the enum has an 
underlying numeric base type, such as byte, int, long, etc. By default, each 
constant value is assigned an incrementing integer value starting from 0, 
although this sequence can be interrupted by assigning an explicit integer 
value:

```cs
enum Colors { Red, Green, Blue }
Colors.Red // 0
Colors.Green // 1
Colors.Blue // 2

enum Days: byte { Sat = 1, Sun, Mon, Tue, Wed, Thu, Fri }
Days.Sat // 1
Days.Sun // 2
```

C# enum values can be used with many standard numeric operations, and are often 
heavily used with bitwise operators. A C# enum value is a constant value, and 
is internally treated as a numeric literal by the compiler. In any C# enum 
declaration, only constant numeric values can be explicitly assigned to an enum 
member, although constant reduction is permitted:

```cs
enum UriComponents {
  Scheme = 0x1,
  UserInfo = 0x2,
  Host = 0x4,
  Port = 0x8,
  Path = 0x10,
  Query = 0x20,
  Fragment = 0x40,
  AbsoluteUri = Scheme | UserInfo | Host | Port | Path | Query | Fragment
}
```

Although C# enum values are converted to numeric literals by the compiler, 
their type information is preserved. This allows for an enum type to have 
different behavior from a literal numeric type. One example of this behavior is 
how ToString is handled on an enum value:

```cs
enum Numbers { Zero, One, Two }
(int)Numers.Zero // 0
Numbers.Zero.ToString() // Zero
```

The enum type itself has a number of static methods to make it easier to 
program against, including: GetName, GetNames, GetUnderlyingType, IsDefined, 
Parse, and ToObject. Instance members of an enum type include HasFlag and 
CompareTo.

In TypeScript we treat an enum declaration in a fashion similar to a C# enum, 
with respect to how we handle incremental integer values and explicitly 
assigned values. We effectively emit an enum as an object literal:

```ts
// TypeScript
enum Colors { Red, Green, Blue }

Colors.Red // 0

// JavaScript
var Colors;
(function (Colors) {
  Colors[Colors[0] = "Red"] = 0;
  Colors[Colors[1] = "Green"] = 1;
  Colors[Colors[2] = "Blue"] = 2;
})(Colors || (Colors = {}));

Colors.Red // 0
```

In this way, you can use `Colors.Red` to get the value 0, and `Colors[0]` to 
get the value "Red".  As a performance optimization we also have what we call 
"const enums". A const enum can be completely erased by the compiler:

```ts
// TypeScript
const enum Colors { Red, Green, Blue }

Colors.Red // 0

// JavaScript
0 /*Colors.Red*/ // 0
``` 

I think a general proposal for ES enums would be a combination of the above 
approaches, with some additions:

* An enum can be a declaration or an expression.
* The body of an enum consists of a new lexical scope.
* Enum members are standard JavaScript identifiers.
* Enum members are automatically assigned an incrementing integer value, 
starting at zero.
* Enum members can be explicitly assigned to an integer value, or another enum 
value.
* Within the body of an enum, Enum members can be accessed in the initializer 
without qualification.
* Within the body of an enum, Enum members are lexically declared names and 
cannot be accessed before they are defined (TDZ).
* An enum declaration can be called as a function to convert a string or 
numeric value into the enum value, making enum types distinct from numbers and 
from each other. [1]
* The result of `typeof` on an enum value is `enum`.
* Enum values support (at least) the following operators, returning an enum 
value of the same type: + (unary), - (unary), ~, + (binary), - (binary), | 
(binary), & (binary), ^ (binary).
* Any binary operation between two enums of different types is a TypeError. [1]
* Any binary operation between an enum and a number first converts the number 
to the enum type. If the number is not an integer it is a TypeError.
* Any binary operation between an enum and a string first converts the enum 
into the string value for that enum based on the enum member's JavaScript 
identifier (if present), or the string representation of its integer numeric 
value. [2]
* Calling Number() with an enum value as its first argument returns its 
underlying number value.
* Calling String() with an enum value as its first argument returns the string 
value for the enum member that defines the number (if present), or the string 
representation of its integer numeric value. [2]
* Calling the valueOf() instance method on an enum value has the same effect as 
Number() above.
* Calling the toString() instance method on an enum value has the same effect 
as String() above. [2]
* Two enum members on the same enum or differing enum types with the same 
underlying integer value are equivalent (==) but not strictly/reference 
equivalent (===). [1]

I think these rules could satisfy both anyone who needs enum values to be 
numeric (to support bitwise operations, bitmasks, ordinal indices, etc.) a

RE: Reflection to know if executed within a generator/async ?

2015-12-03 Thread Ron Buckton
I agree with Bradley, and kindly refer you to this oft referenced blog post 
regarding synchronous and asynchronous APIs: 
http://blog.ometer.com/2011/07/24/callbacks-synchronous-and-asynchronous/

Ron





From: Bradley Meck
Sent: Thursday, December 3, 2015 8:57 AM
To: Andrea Giammarchi
Cc: es-discuss@mozilla.org
Subject: Re: Reflection to know if executed within a generator/async ?


I am against any semantics that expose how a function is used. I struggle and 
many others do when this occurs in CSS (display varies depending on container). 
I would also be hesitant to encourage things acting both synchronously and 
asynchronously depending on how they are used. Changing temporal behavior 
depending on usage is asking for race conditions.

On Thu, Dec 3, 2015 at 10:37 AM, Andrea Giammarchi 
mailto:andrea.giammar...@gmail.com>> wrote:
Uhm... you never closed that "will this value be  thing and I'm expecting a 
"dary" answer like in few emails but my whole point is consuming  an API in 
different scenarios: held or synchronous.

You can always create an API that always returns a Promise, that's nothing new 
for the language, but can you decide if it's he case to absolutely return a 
promise 'cause any other value would cause trouble within that generator or 
async function?

On Thu, Dec 3, 2015 at 4:15 PM, John Lenz 
mailto:concavel...@gmail.com>> wrote:
I don't think being executed in a generator or async function is a good signal 
that a promise should be returned (something needs to "await" the promise).   
The async function is really a chain of synchronous code split at various 
points, during the synchronous parts the code would still need to be 
synchronous and returning a promise would be wrong.   The real data you need is 
"will this value be consumed by an 'await' expression or be used to resolve a 
Promise and, in the general case,  that is not something that can't be answered 
at the time your example function is executing.

On Thu, Dec 3, 2015 at 4:15 AM, Andrea Giammarchi 
mailto:andrea.giammar...@gmail.com>> wrote:
Hi there,
  just writing down some thoughts about being able to understand if a 
method/function has been  executed within a generator/async and is being 
yielded/awaited.

Rationale: API that would like to behave synchronously in some case, returning 
Promises in other cases.

Example:

```js
function fileGetContent(fileName) {
  // random example
  if (held) {
return fetch(fileName).then((r)=>r.text());
  } else {
var xhr = new XMLHttpRequest;
xhr.open('GET', fileName, false);
xhr.send(null);
return xhr.responseText;
  }
}
```

Above example will virtually return always the same type and it could work 
inside a generator or an  async function as long as it's being held.

Does any of this make sense? Is it worth exploring this pattern?

Thanks for any sort of thought.

Best  Regards





___
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: Decorators for functions

2015-10-22 Thread Ron Buckton
> -Original Message-
> From: Andrea Giammarchi [mailto:andrea.giammar...@gmail.com]
> Sent: Thursday, October 22, 2015 12:53 PM

> Ron, there's **no way** you can distinguish a class from  a generic function
> in current specifications.

Yes, this is true. However, decorators aren't in the current specification 
either. If this becomes a must-have then we should investigate an API or 
meta-property that could expose this information, as I mentioned in my previous 
reply.

> Having one argument won't tell me much, having a way to know that is not a
> class I need to decorate (traits/mixins) but just a function, so ignoring its
> prototype and do something else, would be cool but it's unfortunately not
> possible or portable.
> 
> How would you distinguish between a class or a function for a generic
> decorator? Or all you are saying is that decorators shouldn't be able to
> distinguish at all between a class, rather than a function?

While I think it would be a valuable feature to be able to distinguish between 
a class and a function, it may make it difficult to properly reason between an 
ES6 class and an ES5/3 function-as-a-class-constructor. The possibility of 
adding a "call constructor" further complicates this.

It's useful to be able to disambiguate within the decorator, so I can know 
whether I would need to maintain a prototype chain:

```js
function someDecorator(target) {
  // using "function.decoration" as a possible meta-property
  if (function.decoration === "class") {
return class extends target {
  constructor(...args) {
// do something in constructor...
super(...args);
  }
};
  }
  else if (function.decoration === "function") {
return function(...args) {
  // do something in function...
  return target(...args);
};
  }
}
```

Alternatively, it would be interesting if all class declarations were 
implicitly given a Symbol.class property on the constructor declaration. This 
way older function-as-a-class-constructor implementations could opt-in to 
stating "I'm a class":

```js
function someDecorator(target) {
  if (arguments.length !== 1) throw new TypeError(); // only for class/function
  if (target.hasOwnProperty(Symbol.class)) {
// class
  }
  else {
// function
  }
}

// up-level
@someDecorator
class ES6Point {
  constructor(x, y) {
this.x = x;
this.y = y;
  }
}

// down-level
function Point(x, y) {
  this.x = x;
  this.y = y;
}
Point[Symbol.class] = true;
Point = someDecorator(Point) || Point;
```

Ron 

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


RE: Decorators for functions

2015-10-22 Thread Ron Buckton
Andrea,

Is your concern about disambiguating the usage of a decorator at the call site 
or within the body of the decorator? In the current proposal, you can decorate 
a class member, or the class itself.

When decorating a class member, three arguments are passed to the decorator: 
The target, the property key (string or symbol), and the descriptor. When 
decorating the class, one argument is passed to the decorator: The constructor 
function. Generally this means that you can disambiguate the usage of the 
decorator based simply on `arguments.length`, or testing for `undefined` for 
the property key or descriptor.

Would it be better to have a more consistent way to disambiguate the usage of a 
decorator from within the decorator? This could be addressed with something 
like a Reflect.getDecoratorUsage API or a `function.decoration` meta-property 
or the like. Consider something like:

```js
function memoize(target, key, descriptor) {
  switch (Reflect.getDecoratorUsage(arguments)) {
case "class":
  // `target` is the class constructor. `key` and `descriptor` are 
undefined.

case "function":
  // `target` is the function. `key` and `descriptor` are undefined.

case "method":
  // `target` is the object containing the method (e.g. constructor
  // for a static method, prototype for a prototype method, or
  // instance for an object literal method).
  // `key` is the string or symbol property name for the method.
  // `descriptor` is the property descriptor for the method.

case "accessor":
  // `target` is the object containing the accessor (e.g. constructor
  // for a static accessor, prototype for a prototype accessor, or
  // instance for an object literal accessor).
  // `key` is the string or symbol property name for the accessor.
  // `descriptor` is the property descriptor for the accessor.
  }
}
```

Ron

From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Andrea 
Giammarchi
Sent: Thursday, October 22, 2015 10:47 AM
To: Yongxu Ren 
Cc: es-discuss mailing list 
Subject: Re: Decorators for functions

Removing ambiguity is my point since the very first post: current proposal is 
about a target, a property name, and a descriptor for such property ... having 
functions/variables decorators have no target (in strict mode undefined can't 
be a target, right?) and not necessarily a descriptor, or if any, always a data 
one with fields that makes no  sense (like enumerable within a private scope 
... what does that even mean)

I'm all in for a distinct, separate, syntax to decorate "callables" or other 
variables as long as the current proposal will make for ES7 and won't be 
bothered by this different requirement.

Regards



On Thu, Oct 22, 2015 at 6:29 PM, Yongxu Ren 
mailto:renyon...@gmail.com>> wrote:
I don't think

> ```@@ or @() or @::meomize```

would really help much, you can tell what the decorator does by simply looking 
at its name. And looks like you can not use @ and @@ for the same decorator 
function without adding extra condition checking inside the function.

There are two patterns that we have discussed here, they are actually quite 
distinct. I still think we should support decorator on variables, but maybe we 
should have 2 distinct syntax for the normal decorators and "ambient 
decorators"(from Jonathan's post):

1.  decorator that alter the code behavior,  the currently proposed decorator. 
Such as ```@memoize```

2. decorator that absolutely does not alter the code behavior, only used for 
optimization, checking or debugging. Instead of @, a distinct syntax will be 
much clearer ex.```@annotatition@``` (Maybe it should be called annotation 
instead?):
```
@deprecated@

@number,number=>string@/*type checking*/

@debug("this message will only print in development mode")@
```

it sounds like terrible idea to have a decorator in code that you can not 
figure out if it will alter the code behavior by looking at it. I do like to 
see all the new ideas been added into javascript, but it is also necessary to 
eliminate the ambiguity whenever possible.


On Thu, Oct 22, 2015 at 11:20 AM, Jonathan Bond-Caron 
mailto:jbo...@gdesolutions.com>> wrote:
On Thu Oct 22 07:44 AM, Andreas Rossberg wrote:
> > determined at creation time, allowing for massive engine optimization,
>

Ya I'm not sure from which hat "massive engine optimization" comes from?

What's meant is likely using decorators as annotations (compile time 
optimizations hints):
http://www.google.com/patents/US7013458

Or 'ambient decorators':
https://github.com/jonathandturner/brainstorming/blob/master/README.md#c6-ambient-decorators

RE: Decorators for functions

2015-10-20 Thread Ron Buckton
I can think of numerous examples of how decorators could apply to functions, 
and I’ve added them to a 
gist [1] for easier 
consumption. It’s true that simple decorators for functions can work as simply 
as function calls, but this becomes a bit unwieldy if you need to compose 
multiple decorators on a single function.

Consider a scenario combining decorators providing runtime type information as 
an annotation with one that adds runtime type checking. With decorators this 
might be:

```js
@paramtypes(() => [Number, Number])
@returntype(() => Number)
@checked
function add(x, y) { return x + y }
```

If I just use function expressions, this is feasible if a bit awkward:

```js
const add =
paramtypes(() => [Number, Number])(
returntype(() => Number)(
checked(
function (x, y) { return x + y; })))
```

It feels a bit developer-hostile to have to rebalance parentheses if you want 
to add a decorator, and there are ASI hazards if you misplace an opening paren. 
Also, you can no longer infer the function name “add” from the const binding.

Using `::` isn’t a great replacement either, as there are many hazards such as:

```js
// The following means “call `decorator` with `this` bound to the function 
object”.
// Also, it becomes impossible to infer the function name “a” from the let 
binding.
let a = function() { }::decorator(x)

let b = function() { }
::some.decorator(x) // ASI hazard as `::` can be either prefix or infix.
```

One of the initial drivers for decorators was class methods, as there’s no 
expression context immediately inside the class body in which you can use 
either of the above scenarios. This necessitated a declarative form for 
decorators to allow these scenarios to exist. Having parity across class 
methods, classes, and functions (of all kinds) presents a more consistent story 
to developers. The upswing in decorator use in both TypeScript and Babel has 
been very positive, with libraries like Angular leveraging decorators heavily 
in their codebase. Since we introduced decorators into TypeScript, we’ve had a 
fair bit of feedback requesting support for function decorators.

I do think function decorators should wait until the Class/Property decorators 
proposal advances further along the standards track. Axel’s initial 
concerns/questions around hoisting are valid and there isn’t a clear consensus 
on the semantics for functions. That said, I’ve been mostly in the camp of 
introducing TDZ for function declarations that have decorators. Decorators are 
a new syntactic form and we have the opportunity to communicate this caveat 
with the development community by the time the feature lands. It seems easy 
enough to explain that:

```js
@decorator
function func() { }
```

Is the equivalent of:

```js
let func = @decorator function() { }
```

Introducing TDZ allows to generally warn early as part of the static semantics, 
so developers won’t fall into a well with respect to adding a decorator to a 
function and not being able to quickly understand how that change affects the 
behavior of their code.

I’m not certain what the current plan of record is, but the best approach may 
be:


1.   Advance and get consensus on the Class/Property decorators proposal

2.   Draft a separate proposal for decorators on function expressions, 
generator function expressions, and arrows

3.   Draft a separate proposal for decorators on function declarations

Steps 1 and 2 above shouldn’t be significantly difficult and don’t necessarily 
introduce any major new semantics outside of the decorators themselves. Step 3 
covers a thornier issue as it not only introduces the new semantics of 
decorators but also introduces side-effects due to hoisting.

Ron

[1] https://gist.github.com/rbuckton/37e944f7986e6833949e


From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Andrea 
Giammarchi
Sent: Tuesday, October 20, 2015 3:34 AM
To: Axel Rauschmayer 
Cc: es-discuss mailing list 
Subject: Re: Decorators for functions

You haven't provided a single use-case example, like how are you going to 
decorate a function or why.

IMO if implemented it will be incompatible with non ES6 code unable to 
distinguish between classes and functions unless fully transpiled, making 
decorators less portable.

One thing I like about current state is that you can use decorators even in ES5 
browsers [1]

Just my 2 cents, Regards


[1] as shown in the second example of the universal mixin module 
https://github.com/WebReflection/universal-mixin#universal-mixin-

On Tue, Oct 20, 2015 at 10:30 AM, Axel Rauschmayer 
mailto

RE: Exporting Symbols

2015-10-15 Thread Ron Buckton
Wouldn’t this work?

our-symbols.js:
```js
export const SpecialSymbol = Symbol("SpecialSymbol");
```

their-consumer.js
```js
import { SpecialSymbol } from "our-symbols";

export const features = {
[SpecialSymbol]: true
};
```

our-features.js
```js
import { SpecialSymbol } from "our-symbols";
import { features } from "their-consumer";

if (features[SpecialSymbol]) {
  // …
}
```

This uses an export named “features”, though in practice it’s pretty much the 
same as using “export default”. While the “features” identifier could 
theoretically be some other “features” with a different meaning, you can still 
detect the presence of your special symbol.

Ron

From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Francisco 
Tolmasky
Sent: Thursday, October 15, 2015 10:47 AM
To: Logan Smyth 
Cc: es-discuss@mozilla.org
Subject: Re: Exporting Symbols

There are special features we want to expose if a module defines a certain key. 
However, we’d like to not rely on certain names just because there’s some 
chance they came up with it themselves. If it was a symbol that we gave them 
access to, it would be impossible for this to be the case, they would have had 
to grab the symbol from us:

var SpecialSymbol = require(“our-symbols”).SpecialSymbol;

export { whatever as SpecialSymbol }

The difficulty I’m having right now is being torn by two competing “best 
practices”: on the one hand, you can’t do what I did above for the runtime 
reasons, on the other hand you CAN actually pull it off using the export 
default strategy, and in that situation it technically is safer for us to use 
our special symbol instead of relying on a string match.


On Thu, Oct 15, 2015 at 8:10 AM, Logan Smyth 
mailto:loganfsm...@gmail.com>> wrote:
The main issue is that modules are statically analysable and imports/exports 
are processed before the module executes, and the behavior of a symbol is by 
definition a runtime thing. Until the code executes, there would be no symbol 
object, and there would be no way to know what thing was being imported 
imported / exported.

The primary benefit of symbols is that they are unique, and cannot collide 
unless you have a reference to them. Module exports have full control over 
their names and don't have the same collision issues that objects and classes 
generally do. What is the benefit you are hoping to get from exposing these 
values on symbols instead of string keys?



On Thu, Oct 15, 2015 at 12:14 AM, Francisco Tolmasky 
mailto:tolma...@gmail.com>> wrote:
Not sure if it isn’t the case, but it seems the only way to export symbols 
right now is:

```js
export default { [Symbol(“something”)]: blah }
```

It would be nice if “symbol literals” could somehow be supported. In 
particular, I can imagine this sort of thing becoming common:

export { “5.4” as Symbol(“version”) }

Or, even better (but harder since its now more expression):

import VersionSymbol from “symbols"
export { “5.4” as VersionSymbol }

I’m currently writing an API where there are expected methods stored in 
symbols, but this forces exporting one default object instead of being able to 
lay them out individual.

Thanks,

Francisco

--
Francisco Tolmasky
www.tolmasky.com
tolma...@gmail.com

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




--
Francisco Tolmasky
www.tolmasky.com
tolma...@gmail.com
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Template strings as a template language.

2015-09-13 Thread Ron Buckton
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&data=01%7c01%7cron.buckton%40microsoft.com%7ce705066eae3849ee21f008d2bc913033%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=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&data=01%7c01%7cron.buckton%40microsoft.com%7ce705066eae3849ee21f008d2bc913033%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=Vk9C%2fonHktgLCsW%2f395PrpBWefRcs6XFqJk7HTVbunE%3d
>>
>
>
>
> --
> Cheers,
> --MarkM
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://na01.safelinks.protection.outlook.com/?url=https%3a%2f%2fmail.mozilla.org%2flistinfo%2fes-discuss&data=01%7c01%7cron.buckton%40microsoft.com%7ce705066eae3849ee21f008d2bc913033%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=Vk9C%2fonHktgLCsW%2f395PrpBWefRcs6XFqJk7HTVbunE%3d
>



--
Isiah Meadows
___
es-discuss mailing list
es-discuss@mozilla.org
https://na01.safelinks.protection.outlook.com/?url=https%3a%2f%2fmail.mozilla.org%2flistinfo%2fes-discuss&data=01%7c01%7cron.buckton%40microsoft.com%7ce705066eae3849ee21f008d2bc913033%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=Vk9C%2fonHktgLCsW%2f395PrpBWefRcs6XFqJk7HTVbunE%3d
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: What do you think about a C# 6 like nameof() expression for JavaScript.

2015-08-09 Thread Ron Buckton
While its true most IDE's can search for references in strings, `nameof` takes 
some of the guesswork out of determining whether a substring that matches a 
symbol refers to the symbol or is merely part of the sentence.

That said, `nameof` is primarily a convenience for an IDE.

Ron

Sent from my Windows Phone

From: Isiah Meadows<mailto:isiahmead...@gmail.com>
Sent: ‎8/‎8/‎2015 8:57 PM
To: Ron Buckton<mailto:ron.buck...@microsoft.com>; Behrang 
Saeedzadeh<mailto:behran...@gmail.com>; EcmaScript Discuss Mailing 
List<mailto:es-discuss@mozilla.org>
Subject: Re: What do you think about a C# 6 like nameof() expression for 
JavaScript.


To be honest, most larger IDEs also search for references in strings, and even 
if it doesn't, any decent editor can do a regex replace of `identifierName` 
without problem. I don't see much of a problem here. Also, do you know of any 
other language that has this at the syntax level (not macro)?

On Sat, Aug 8, 2015, 23:12 Ron Buckton 
mailto:ron.buck...@microsoft.com>> wrote:
One of the main purposes of the `nameof` operator is to provide the string 
value of a symbol, so that if you perform a "Rename" refactoring of that symbol 
that the change is also reflected. This is primarily for cases where you 
perform precondition assertions tied to an argument:

```
  ...
  static void Method(string x) {
if (x == null) throw new ArgumentNullException(nameof(x));
...
  }
```

Now, if I later rename `x`, I don't need to also find any string literals of 
"x" and manually update them.

There are other uses of `nameof`, but they all boil down to roughly the same 
thing.

Ron

From: Isiah Meadows<mailto:isiahmead...@gmail.com>
Sent: ‎8/‎8/‎2015 7:23 PM
To: Behrang Saeedzadeh<mailto:behran...@gmail.com>; EcmaScript Discuss Mailing 
List<mailto:es-discuss@mozilla.org>
Subject: Re: What do you think about a C# 6 like nameof() expression for 
JavaScript.


Call me crazy, but I don't see anything that couldn't be done more concisely 
with a string literal. Is it supposed to be able to do this?

```js
function foo(x) {
  return nameof(x);
}

foo(bar); // "bar";
```

In that case, the engine would have to keep track of usages as well, in a 
similar sense as `arguments.callee`, and if it were a function, it would make 
optimization quite difficult, as engines don't have the capacity to statically 
analyze that such a function is used.

If it is like `typeof`, we now have a breaking change - a keyword that was a 
valid Identifier before.

```js
// Error?
function nameof(value) {
  return 
value.name<https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fvalue.name&data=01%7c01%7cron.buckton%40microsoft.com%7ca2e2c4d35400435810d008d2a061897d%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=pwV45avF9RX6COETpoLIY4EF%2bmCVmk6kEEmLc2JXSCY%3d>;
}

var bar = {name: 2};
nameof(bar); // "bar" or 2?
```

I don't think this is going to work out in practice, not in ECMAScript proper. 
You might appreciate Sweet.js, though.

On Sat, Aug 8, 2015, 21:27 Behrang Saeedzadeh 
mailto:behran...@gmail.com>> wrote:
Forgot to mention that nameof works with local variables too:

function foo() {
 var aNum = 1;
 console.log(nameof(aNmum), aNum);
}


On Sat, Aug 8, 2015 at 10:38 AM Behrang Saeedzadeh 
mailto:behran...@gmail.com>> wrote:

So basically we could use it like this:


function aFunc(aParam) {
throw new Error(nameof(aParam));
}



and nameof(aParam) would return the string "aParam".


This is possible to do even right now using arguments.callee and some hacky 
code, but having it built-in to spec would be nicer IMHO.

--
Best regards,
Behrang Saeedzadeh
--
Best regards,
Behrang Saeedzadeh
___
es-discuss mailing list
es-discuss@mozilla.org<mailto:es-discuss@mozilla.org>
https://mail.mozilla.org/listinfo/es-discuss<https://na01.safelinks.protection.outlook.com/?url=https%3a%2f%2fmail.mozilla.org%2flistinfo%2fes-discuss&data=01%7c01%7cron.buckton%40microsoft.com%7ca2e2c4d35400435810d008d2a061897d%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=7DHMx5gTd2OexSlKscSrKlMIxABMUkOKRC%2fuCbc6pWk%3d>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: What do you think about a C# 6 like nameof() expression for JavaScript.

2015-08-08 Thread Ron Buckton
One of the main purposes of the `nameof` operator is to provide the string 
value of a symbol, so that if you perform a "Rename" refactoring of that symbol 
that the change is also reflected. This is primarily for cases where you 
perform precondition assertions tied to an argument:

```
  ...
  static void Method(string x) {
if (x == null) throw new ArgumentNullException(nameof(x));
...
  }
```

Now, if I later rename `x`, I don't need to also find any string literals of 
"x" and manually update them.

There are other uses of `nameof`, but they all boil down to roughly the same 
thing.

Ron

From: Isiah Meadows
Sent: ‎8/‎8/‎2015 7:23 PM
To: Behrang Saeedzadeh; EcmaScript Discuss Mailing 
List
Subject: Re: What do you think about a C# 6 like nameof() expression for 
JavaScript.


Call me crazy, but I don't see anything that couldn't be done more concisely 
with a string literal. Is it supposed to be able to do this?

```js
function foo(x) {
  return nameof(x);
}

foo(bar); // "bar";
```

In that case, the engine would have to keep track of usages as well, in a 
similar sense as `arguments.callee`, and if it were a function, it would make 
optimization quite difficult, as engines don't have the capacity to statically 
analyze that such a function is used.

If it is like `typeof`, we now have a breaking change - a keyword that was a 
valid Identifier before.

```js
// Error?
function nameof(value) {
  return 
value.name;
}

var bar = {name: 2};
nameof(bar); // "bar" or 2?
```

I don't think this is going to work out in practice, not in ECMAScript proper. 
You might appreciate Sweet.js, though.

On Sat, Aug 8, 2015, 21:27 Behrang Saeedzadeh 
mailto:behran...@gmail.com>> wrote:
Forgot to mention that nameof works with local variables too:

function foo() {
 var aNum = 1;
 console.log(nameof(aNmum), aNum);
}


On Sat, Aug 8, 2015 at 10:38 AM Behrang Saeedzadeh 
mailto:behran...@gmail.com>> wrote:

So basically we could use it like this:


function aFunc(aParam) {
throw new Error(nameof(aParam));
}



and nameof(aParam) would return the string "aParam".


This is possible to do even right now using arguments.callee and some hacky 
code, but having it built-in to spec would be nicer IMHO.

--
Best regards,
Behrang Saeedzadeh
--
Best regards,
Behrang Saeedzadeh
___
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: let function

2015-05-14 Thread Ron Buckton
I proposed something similar to this among the folks investigating decorators 
for ES7:

https://github.com/jonathandturner/decorators/issues/17

In this case, it was for a `const function`, as a means to allow a decorator on 
a function declaration, as adding the `const` (or `let`) would introduce TDZ 
and set the right expectations for how decorators would be executed.

Ron

From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Alexander 
Jones
Sent: Thursday, May 14, 2015 1:37 PM
To: Garrett Smith
Cc: Bergi; es-discuss@mozilla.org
Subject: Re: let function

Good points. All the more reason to throw out declarations as statements in 
favour of let/const/var, which we all have to understand well anyway, for other 
types of variable.

Cheers

On Thursday, May 14, 2015, Garrett Smith 
mailto:dhtmlkitc...@gmail.com>> wrote:
On 5/14/15, Alexander Jones > wrote:
> Ah, thanks for explaining! What about the Temporal Dead Zone of let,
> or const binding semantics, for those of us who are obsessive enough to
> desire that kind of thing everywhere?
>
Let a constructive discussion about this proposal take place.

"The specification," can most reasonably be taken among programmers to
mean "the latest version of  specification" not "draft specification"
or "proposal". Evangelists and standards geeks tend to miscall "draft"
"specification" to the misfortunate effect that it misleads developers
into believing that drafts are normative, final, etc. That's quite a
bit worse than the abrasiveness and confusion seen here, but hopefully
they can stop and a discussion can take place.

http://www.ecma-international.org/ecma-262/5.1/#sec-12

Because of these irreconcilable differences, the use of a
FunctionDeclaration as a Statement results in code that is not
reliably portable among implementations. It is recommended that
ECMAScript implementations either disallow this usage of
FunctionDeclaration or issue a warning when such a usage is
encountered.

The decision for such wording probably came from discussions and time
constraints of getting ES5 done. The problem of FunctionDeclaration
arose from implementations in JScript (see "[MS-ES3EX]" and language
extensions in Spidermonkey and others. It progressed to misstatements
in presentations and books. For more on this, see "Named function
expressions demystified".


> On Thursday, May 14, 2015, Bergi > wrote:
>
>> Alexander Jones schrieb:
>> > On Thursday, May 14, 2015, Domenic Denicola 
>> > > wrote:
>> >
>> >>   They can, in fact, be scoped in a for loop.
>> >
>>
>>> That's not what I see, in strict mode at least, which I assume most
>>> people
>>> consider de facto by now!
>>>
>>> From V8:
>>>
>>>  SyntaxError: In strict mode code, functions can only be declared at
>>> top
>>> level or immediately within another function.
>>>
>>
>> That's ES5. In ES6, function declarations are allowed in blocks - with
>> the
>> new block scope semantics. This was only possible as ES5 strict mode held
>> that spot open so now it doesn't break anything :-)
>> Yes, it will need a while until people get accustomed to that.
>>
>>  Bergi
>> ___
>> es-discuss mailing list
>> es-discuss@mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>


--
Garrett
@xkit
ChordCycles.com
garretts.github.io
personx.tumblr.com
___
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 Ron Buckton
Oops, was think in batch for a minute there.

Sent from my Windows Phone

From: Brendan Eich<mailto:bren...@mozilla.org>
Sent: ‎4/‎7/‎2015 6:23 PM
To: Ron Buckton<mailto:ron.buck...@microsoft.com>
Cc: Caitlin Potter<mailto:caitpotte...@gmail.com>; 
es-discuss@mozilla.org<mailto:es-discuss@mozilla.org>
Subject: Re: Existential Operator / Null Propagation Operator

Ron Buckton wrote:
>> >  The reduce/reduce conflict recognizing a left sentential form '[' E ']'
>> >  vs. M '?' '[' E ']' shows the fatal ambiguity.
>> >
>> >  /be
>
> There is also ambiguity due to ASI vs. a ConditionalExpression:
>
> ```
> obj ? [ expr ]
> :label
> ```
>
> Ron

Colon goes after label :-P. But the problem is bounded lookahead,
ideally k=1. We are not specifying backtracking...

/be
___
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 Ron Buckton
Brendan Eich wrote:
> Brendan Eich wrote:
> > Caitlin Potter wrote:
> >>   6, 2015 at 5:42 PM, Brendan Eich >> >  wrote:
> >> >
> >> >>/  Did you keep backward compatibility? `x?.1:y` must continue to
> >> work.
> >> />
> >> >
> >> >​This is why I suggested a leading operator (`?a.?b()`) because it
> >> seems
> >> >like it would have the least potential for conflict with existing
> >> >valid syntax​
> >>
> >> What about something like
> >> MemberExpression[?Yield]   ?|.|  IdentifierName
> >> MemberExpression[?Yield]   ?*[*  Expression[In, ?Yield]  |]|
> >> Context specific to MemberExpressions, as far as I'm aware there's no
> >> otherwise valid ternary expression that could be mixed up for it, and
> >> it wouldn't need a cover grammar?
> >>
> >
> > We can try being this precise, as you say -- but we cannot then handle
> > x?(y) as CoffeeScript does. Instead of being neither fish nor fowl,
> > better to be fowl with leading ?, or use a distinct and regular syntax
> > that handles all the cases we want. My two cents,
> 
> The reduce/reduce conflict recognizing a left sentential form '[' E ']'
> vs. M '?' '[' E ']' shows the fatal ambiguity.
> 
> /be

There is also ambiguity due to ASI vs. a ConditionalExpression:

```
obj ? [ expr ] 
:label 
```

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


RE: Array.prototype.find - Proposal for (breaking) change of API

2015-04-07 Thread Ron Buckton
Even more off-topic, I’m sure, but with http://github.com/rbuckton/queryjs (a 
query library over iterables) and ES6 you can do:

```
import { Query } from './query';
let files = ["main.md", "backup.md"];
let base = "/my/root";
let found = Query
  .from(files)
  .map(file => path.resolve(base, file))
  .filter(file => fs.existsSync(file))
  .first();
```

Ron

From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Andrea 
Giammarchi
Sent: Tuesday, April 7, 2015 1:40 PM
To: Alexander Jones
Cc: Martin Heidegger; es-discuss@mozilla.org
Subject: Re: Array.prototype.find - Proposal for (breaking) change of API

not sure if off topic but

  * you need a with statement to use lodash like that
  * ... the following ...

```
let found = first(filter(
  map(files, _ => path.resolve(base, _)),
  fs.existsSync
));
```

is a very wasteful pattern ... have you ever heard of `some` ?

```
let found;
some(files, _ => fs.existsSync(found = path.resolve(base, _)) || (found = '') 
|| false);
```

It could bring few alchemies in ;-)


On Tue, Apr 7, 2015 at 9:14 PM, Alexander Jones 
mailto:a...@weej.com>> wrote:
You need lazy sequences aka iterators. They give you the rather optimal:

let found = first(filter(
map(files, _ => path.resolve(base, _)),
fs.existsSync
));

Libs like lodash and lazy.js provide the bits you need, which are actually 
fairly trivial to build on top of nice new ES6 iterators if you want.

Alex


On Tuesday, April 7, 2015, Martin Heidegger 
mailto:martin.heideg...@gmail.com>> wrote:
I am probably very late to the game but I just read about harmonies 
“Array.prototype.find” and found that it might be worth considering a change in 
way it works. Its not a drastic change but it would break the compatibility to 
the current setup. I understand that the chances for this going through will be 
slim but since I would like to give it a shot anyways:

Currently the API uses a callback function that has to return a boolean to 
identify the item that has been found. This is good because find & findIndex 
can use the same methods but it also has a drawback.

Problem: Say you have a list of items that need to be processed before you know 
if you “found” the item. Then you will need to process the last item again 
since there is no way to “keep” the result (A) of the find method or you 
preprocess all items using map (B) that will require to process all the items 
even if the first one already matches.

Example:

(BASE)
var files = [“main.md”, “backup.md”]
var base = “/my/root"

(A)
// Specifies `path.resolve` on two places
var found = files.find(function (file) {
   return fs.existsSync(path.resolve(base, file))
}))
if (found)
  found = path.resolve(base, file)

(B)
// Runs `path.resolve` for all items
var found = files.map(function (file) {
  return path.resolve(base, file)
}).find(fs.existsSync)

Proposal (C): I think it might be interesting to have a change of the signature 
so that the return value is not true/false but the value that actually will be 
returned (not undefined):

(C)
var found = files.find(function (file) {
   file = path.resolve(base, file)
   if(fs.existsSync(file))
 return file
});

This way the operations would be minimised, it is still few to write and it 
would make life a bit easier.

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

2015-04-06 Thread Ron Buckton
Wouldn't `.?` as an infix operator be unambiguous, compared to `?.`? There's no 
place other than decimal literals where this would be legal today, and decimal 
literals already require either parenthesis or an extra dot to perform a 
property access in any event. With that lexeme, `x.?1:y` would be unambiguously 
an error. `1.?x:y` is unambiguously a conditional, while `1..?x:y` is 
unambiguously a null-propagating property access on the numeric literal `1.`.

Ron


-Original Message-
From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Brendan 
Eich
Sent: Monday, April 6, 2015 3:35 PM
To: Matthew Robb
Cc: es-discuss
Subject: Re: Existential Operator / Null Propagation Operator

Yeah, and it would line up with cover grammar needed for refutable-by-default 
patterns.

/be

Matthew Robb wrote:
>
> On Mon, Apr 6, 2015 at 5:42 PM, Brendan Eich  > wrote:
>
> Did you keep backward compatibility? `x?.1:y` must continue to work.
>
>
> ​This is why I suggested a leading operator (`?a.?b()`) because it 
> seems like it would have the least potential for conflict with 
> existing valid syntax​
>
>
>
> - Matthew Robb
___
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: Forwarding `return()` in generators

2015-03-24 Thread Ron Buckton
Is your goal to wrap a generator, as it seems you are propagating the exception 
of the caller by calling iterator.throw(). However, you do not seem to be 
propagating the sent value, so the protocol here isn’t fully implmeneted.

If you just want to iterate values (and don’t really care about the return 
value of the iterable or propagating a thrown exception, you could write:

```js
function* take(n, iterable) {
  n |= 0;
  if (n <= 0) {
return;
  }
  // let for..of call return()
  for (let value of iterable) {
yield value;
if (n-- <= 0) {
  return;
}
  }
}
```

If you want to support the full communication channel of a generator, you could 
write:

```js
function* take(n, iterable) {
  let iterator = iterable[Symbol.iterator]();
  let step = () => iterator.next();
  n |= 0;
  // try..finally outside of loop
  try {
let sent;
while (n > 0) {
  let { value, done } = step();
  if (done) {
return value;
  }
  n--;
  // try..catch local to the yield
  try {
sent = yield value;
step = () => iterator.next(sent);
  }
  catch (e) {
if (typeof iterator.throw === "function") {
  step = () => iterator.throw(e);
}
else {
  throw e;
}
  }
}
  }
  finally {
if (typeof iterator.return === "function") {
  iterator.return();
}
  }
}
```

From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Axel 
Rauschmayer
Sent: Tuesday, March 24, 2015 2:28 PM
To: Bergi
Cc: es-discuss list
Subject: Re: Forwarding `return()` in generators

Right, it doesn’t look like one needs to know the returned value when 
forwarding `return()`.

But: you need to guard against other ways of reaching `finally`. Maybe like 
this:

```js
function* take(n, iterable) {
let iterator = iterable[Symbol.iterator]();
n = +n; // make sure it's a number, so that n>0 does never throw
let forwardReturn = true;
try {
while (n > 0) {
let item = iterator.next();
if (item.done) {
forwardReturn = false;
return item.value;
}
yield item.value;
n--;
}
forwardReturn = false;
} catch (e) {
forwardReturn = false;
iterator.throw(e);
} finally {
if (forwardReturn) {
iterator.return();
}
}
}
```
The above code also has the additional nice property that it call `.return()` 
on the iterator when `n` values have been taken out of it.

That’s not what all the other constructs in ES6 do: they only call `return()` 
if iteration stops abruptly.

Also missing from this code: checking whether the iterator actually has the 
methods `return()` and `throw()` and responding accordingly.

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


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


RE: Cancellation architectural observations

2015-03-04 Thread Ron Buckton
> new Promise(resolve => doLater(resolve, cts.token)).then(handleResult);
> setImmediate(() => cts.cancel());

> 
> In this scenario cancel would be called right after the resolve method 
> is called, but before handlerResult is called. For this to work with a 
> cancellation token you would need to pass the token to every step in 
> the chain to both stop work being done and to ignore the 
> result/prevent a handler from being called. Wouldn't it be better if 
> the promise chain took care of this for the programmer?

I can be convinced that CancellationToken registrations should be invoked 
asynchronously, though I wonder if then CancellationTokenSource#cancel should 
return a Promise to observe any errors that occur. 

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


Re: Cancellation architectural observations

2015-03-02 Thread Ron Buckton
The upside of having a separate abstraction for cancellation, is that it 
composes well with async functions:

```js
async function runStockTicker(receiveSymbol, cancellationToken) {
  while (!cancellationToken.canceled) {
var symbols = await fetchSymbols(cancellationToken);
if (!cancellationToken.canceled) {
  for (var symbol of symbols) {
receiveSymbol(symbol);
  }
  await sleep(1000);
}
  }
}

var stopTicker = new CancellationTokenSource();
runStockTicker(..., stopTicker.token);
...
stopTicker.cancel(); // stop the current fetch and the loop
```

Ron

From: es-discuss  on behalf of Tab Atkins Jr. 

Sent: Monday, March 02, 2015 6:21 PM
To: Kevin Smith
Cc: public-script-co...@w3.org; Dean Tribble; es-discuss
Subject: Re: Cancellation architectural observations

On Mon, Mar 2, 2015 at 3:18 PM, Kevin Smith  wrote:
> I'm afraid I don't quite understand.  How is one supposed to create a
> cancelable task with async functions, under your proposed architecture?

I'm not sure!  The mapping between promises and async functions isn't
intuitive to me yet, and I'm not sure how async functions will be able
to produce promise subclasses rather than plain promises.

~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: Cancellation architectural observations

2015-03-02 Thread Ron Buckton
The simplest example is:


```js

function doLater(callback, token) {

  var handle = setImmediate(callback);

  token.register(() => clearImmediate(handle));
}


var cts = new CancellationTokenSource();

doLater(..., cts.token);

cts.cancel();

```


If token registrations occur in a later turn, I have no way to clear the 
handle. I can write the following instead, however:


```js

function doLater(callback, token) {

  setImmediate(() => {

if (token.canceled) return;

callback();

  });

}

```


But in this case, I still have a callback scheduled which may be unnecessary 
overhead. If this were a native API, we could chose to prioritize cancellation 
registrations over promise tasks. Even if the registrations are async, the 
cancellation signal would still need to be observable in a synchronous manner, 
even if only through reading the CancellationToken#canceled property.


Ron



From: Kevin Smith 
Sent: Monday, March 02, 2015 6:42 PM
To: Ron Buckton
Cc: public-script-co...@w3.org; es-discuss
Subject: Re: Cancellation architectural observations


Cancellation

  *   Cancellation signals are produced by the caller and consumed by the 
callee.
  *   Observation a cancellation signal must happen immediately.

This is a crucially important question.  Can you elaborate on why you think 
this is the case?

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


Re: Cancellation architectural observations

2015-03-02 Thread Ron Buckton
> Cancellations should "chain"
> ==
> If you have a cancellable promise p1, and use .then() to produce a new
> promise p2, p2 should also be cancelable, and in the default case,
> should "chain up" to p1 and cause it to cancel as well.

The CTS/Token approach can do this directly without needing a chain, which is 
observable on the p2 via its onrejected handler.

> If you chain multiple promises off of p1, like p2a and p2b, then
> canceling either one of the p2X promises should do nothing, but
> cancelling *both* of them should cancel p1. In other words, p1 can
> ref-count its "child" promises that retain cancellation abilities, and
> cancel itself when everything consuming its result has been cancelled.

> This is important so you don't have to explicitly keep track of every
> single cancelable thing you're doing, if you're only using it to
> immediately chain onward again.  You can just care about the final
> result, and if you end up not needing it, you can cancel it and it
> walks back and tries to cancel everything your result depends on.

CTS partially accomplishes this through linked registrations, though assuming 
that if all chained promises are canceled that the root should be canceled 
could be a mistake:

```js
var rootCts = new CancellationTokenSource();
var configPromise = fetchConfig(rootCts.token);

var alphaCts = new CancellationTokenSource();
var alphaPromise = fetchConfigProperty(configPromise, "alpha", alphaCts.token);

var betaCts = new CancellationTokenSource();
var betaPromise = fetchConfigProperty(configPromise, "beta", betaCts.token);

alphaCts.cancel();
betaCts.cancel();

// do we want to cancel configPromise here? What if we want to enlist via .then 
later?
// if we are sure we want that behavior we can do this explicitly

var requests = new Set();
function fetchConfigProperty(configPromise, name, token) {
  requests.add(token);
  var registration = token.register(() => {
requests.delete(token);
if (requests.size <= 0) { rootCts.cancel(); }
  });
  return configPromise.then(
config => {
  requests.delete(token);
  registration.unregister();
  return config[name];
},
reason => {
  requests.delete(token);
  registration.unregister();
  throw reason;
});
}
```

> Combinators should combine cancellations
> =
>
> If you do `let fp3 = FetchPromise.all(fp1, fp2)`, then an fp3.cancel()
> should try to cancel fp1 and fp2, as noted above.  You want all the
> (cancellation-aware) combinators to be just as friendly as chaining
> directly, for usability.

If the fetch api supports tokens, you could instead do:

```js
var cts = new CancellationTokenSource();
var fp1 = fetch(..., cts.token);
var fp2 = fetch(..., cts.token);
let fp3 = Promise.all([fp1, fp2]);
cts.cancel(); // will cancel fp1 and fp2
```

> You need to be able to "clean" a cancellable promise
> 
>
> If the promise is what carries the cancellation ability, you need to
> be able to observe its value without carrying the cancellability
> around, to prevent spreading power around in an unwanted way (and
> prevent upping the "chained promises" refcount).  This is doable by
> just wrapping it in a standard promise - `Promise.resolve(fetch(...))`
> will return a normal non-cancellable promise.

This behavior is an explicit benefit of CTS, as it does not conflate Promise 
with the cancellation signal, and is very explicit about the source of 
cancellation. If you want to expose a promise to a consumer without 
cancellation, and instead support cancellation internally, you would do the 
following:

```js
// [api.js]
var rootCts = new CancellationTokenSource();
export function getRecord(id) {
  // cancellation not exposed to consumer
  return fetch(id, rootCts.token);
}
export function shutdown() {
  rootCts.cancel(); // cancellation only exposed to consumer via explicit entry 
point
}

// [consumer.js]
import { getRecord, shutdown } from 'consumer';
var fp1 = getRecord(...); // cannot cancel this individual request
var fp2 = getRecord(...);
shutdown(); // cancels all requests through explicit entry point
```

> A cancellation token is basically an ocap, and that means you have to
> keep track of the ocaps explicitly and separately from the promise for
> the result.  This means more value-passing, and when you return
> another cancellable promise in the callback (like
> `fetch(...).then(x=>fetch(...))`), you have to explicitly smuggle that
> cancellation token out of the callback and hold onto both of them.
> Combinators become annoying, as you have to grab *all* of the cancel
> tokens used and hold them together, etc.

That's what linking registrations are for, and you should only need to add 
cancellation to methods where you can explicitly cancel. You wouldn't need 
tokens for every single promise. Also, the token doesn't come "out of the 
callback", but rather is passed in from the caller:

```
var

Re: Cancellation architectural observations

2015-03-02 Thread Ron Buckton
While I agree that many specific use cases of "abort" could be this simple, 
more complex cases might be better satisfied by a separate abstraction. There 
are two issues I see with this approach:


  *   A layer that sits between the promise consumer and the promise producer 
can directly abort the promise.
  *   It is much more complicated to cancel large chunks of asynchronously 
executing code in bulk (such as when navigating to a new page, or shutting down 
an application cleanly).

I have examples of [1] and [2] here: 
https://gist.github.com/rbuckton/256c4e929f4a097e2c16


The gist basically contains four scenarios:

  *   Promise Producer/Cancellation Consumer
  *   Promise Consumer/Cancellation Producer
  *   Promise Consumer/Cancellation Consumer
  *   Cancellation Aggregation

I will adapt these somewhat to your sample here:


Promise Producer/Cancellation Consumer


```js

function fetch(url, config) {

  config || (config = {});

  return new Promise(function (res, rej) {

var xhr = new XMLHttpRequest();

xhr.addEventListener('error', function (pe) { rej(xhr); });

xhr.addEventListener('load', function (pe) { res(xhr); });

if (config.onabort)

  xhr.addEventListener('abort', config.onabort);

if (config.onprogress)

  xhr.addEventListener('progress', config.onprogress);

if (config.token) {

  config.token.register(function () { xhr.abort(); });

}

xhr.open(config.method || 'GET', url, true);

xhr.send(null);

  });

}

```


Promise Consumer/Cancellation Producer


```js

// abort

var cts = new CancellationTokenSource();

fetch('?page', { onabort: console.warn.bind(console), token: cts.token });

cts.cancel();


// with progress too

var cts = new CancellationTokenSource();

fetch('?page', { onabort: console.warn.bind(console), onprogress: 
console.log.bind(console), token: cts.token });

cts.cancel();

```


Promise Consumer/Cancellation Consumer


```js

function markLoading(value) {

  document.querySelector("#loading").style.display = value ? "block" : "none";

}


function fetchPage(token) {

  markLoading(true);

  if (token)

token.register(function() { markLoading(false); });

  return fetch('?page', { token }).then(

value => {

  markLoading(false);

  return value;

},

reason => {

  markLoading(false);

  throw reason;

});
}

```


Cancellation Aggregation


```js

var root = new CancellationTokenSource();


function fetchPage(token) {

  token = token ? new CancellationTokenSource([root.token, token]).token : 
token;

  token.register(function() { markLoading(false); });

  return fetch('?page', { token }).then(

value => {

  markLoading(false);

  return value;

},

reason => {

  markLoading(false);

  throw reason;

});
}


// abort this request

var cts = new CancellationTokenSource();

fetchPage(cts.token);

cts.cancel();


// abort all requests

fetchPage();

fetchPage();

root.cancel();

```


Ron



From: Andrea Giammarchi 
Sent: Monday, March 02, 2015 4:18 PM
To: Ron Buckton
Cc: Dean Tribble; Kevin Smith; public-script-co...@w3.org; es-discuss
Subject: Re: Cancellation architectural observations

So this is my simplified view of the matter ... it already works, and it aborts 
eventually with the ability to ignore the onabort callback.

The config object can have `onabort` that activates the "abort-ability", the 
`onprogress` so that eventually this promise inside a generator can still 
update UIs, and potentially any other sort of property but for demo sake just 
`method` for GET, HEAD, PUT, POST and other requests.

```js
function fetch(url, config) {
  config || (config = {});
  var
xhr = new XMLHttpRequest,
promise = new Promise(function (res, rej) {
  xhr.addEventListener('error', function (pe) { rej(xhr); });
  xhr.addEventListener('load', function (pe) { res(xhr); });
  if (config.onabort)
xhr.addEventListener('abort', config.onabort);
  if (config.onprogress)
xhr.addEventListener('progress', config.onprogress);
  xhr.open(config.method || 'GET', url, true);
  xhr.send(null);
})
  ;
  if (config.onabort)
promise.abort = xhr.abort.bind(xhr);
  return promise;
}
```

abort example:
`fetch('?page', {onabort: console.warn.bind(console)}).abort();`

with progress too
`fetch('?page', {onabort: console.warn.bind(console), onprogress: 
console.log.bind(console)}).abort();`

full request
`fetch('?page', {onabort: console.warn.bind(console), onprogress: 
console.log.bind(console)}).then(console.log.bind(console));`

Why this code? Simply to somehow show that I am all for getting this right, but 
to me it's also probably a simpler m

Re: Cancellation architectural observations

2015-03-02 Thread Ron Buckton
​

In light of Async Functions in ES7, it may make sense to separate the 
abstractions between promises and cancellation. Promises and cancellation 
signals have different use cases:


Promises

  *   Promises are consumed by the caller and produced by the callee.
  *   Observation a promise resolution can only happen in a later turn.
  *   The consumer of a promise cannot directly resolve the promise.

Cancellation

  *   Cancellation signals are produced by the caller and consumed by the 
callee.
  *   Observation a cancellation signal must happen immediately.
  *   The consumer of a cancellation token cannot directly cancel the token.

API Proposal:


class CancellationTokenSource {
  /** Create a new CTS, optionally with an iterable of linked cancellation 
tokens. */
  constructor(linkedTokens?: Iterable);

  /** Gets the cancellation token for this source. */
  get token(): CancellationToken;

  /** Cancels the source and sends a cancellation signal with an optional 
reason (default Error("Operation canceled")). */
  cancel(reason?: any): void;

  /** Cancels the source after a delay (in milliseconds), with an optional 
reason. */
  cancelAfter(delay: number, reason?: any): void;

  /** Prevents any possible future cancellation of the source and removes all 
linked registrations. */
  close(): void;
}

class CancellationToken {
  /** Gets a cancellation token that can never be canceled. */
  static get default(): CancellationToken;
  /** Gets a value indicating whether the cancellation signal was sent. */
  get canceled(): boolean;
  /** If canceled, gets the reason for cancellation if provided; otherwise, 
returns `undefined`. */
  get reason(): any;
  /** If canceled, throws either the reason or a general “Operation Canceled” 
error. */
  throwIfCanceled(): void;
  /**
* Registers a callback to execute immediately when a cancellation signal is 
received.
* The callback can be removed using the `unregister` method of the return 
value.
*/
  register(callback: (reason: any) => void): { unregister(): void };
}


Usage (Abort):


```
// aborts and throws error when canceled
function fetchAsync(url, cancellationToken = CancellationToken.default) {
  return new Promise((resolve, reject) => {
cancellationToken.throwIfCanceled();
var xhr = new XMLHttpRequest();
var registration = cancellationToken.register(() => xhr.abort());
xhr.open("GET", url, /*async*/ true);
xhr.onload = event => {
registration.unregister();
resolve(xhr.responseText);
};
xhr.onerror = event => {
registration.unregister();
reject(xhr.statusText);
}
xhr.send(null);
  });
}

fetchAsync(...).then(...); // as expected

var cts1 = new CancellationTokenSource();
fetchAsync(..., cts1.token).catch(...);
cts1.cancel(new Error("Operation Canceled"); // .catch gets the error and the 
xhr is aborted.


Usage (Ignore):


// ignore operation/stop processing
async function startTicker(receiveSymbol, cancellationToken = 
CancellationToken.default) {
while (!cancellationToken.canceled) {
var symbols = await fetchSymbols();
for (var symbol of symbols) {
receiveSymbol(symbol);
}
}
}

var stopTicker = new CancellationTokenSource();
stopTicker.cancelAfter(5 * 60 * 1000); // stop after 5 minutes.
startTicker(..., stopTicker.token).catch(...); // .catch only gets error from 
`fetchSymbols`.


Ron


From: es-discuss  on behalf of Dean Tribble 

Sent: Monday, March 02, 2015 1:25 PM
To: Kevin Smith
Cc: public-script-co...@w3.org; es-discuss
Subject: Re: Cancellation architectural observations

On Mon, Mar 2, 2015 at 6:32 AM, Gray Zhang 
mailto:otakus...@icloud.com>> wrote:

+1 to the ignore term, I’ve opened an issue about it in 
https://github.com/promises-aplus/cancellation-spec/issues/14

I have little attachment to any term, but there's value in keeping terminology 
that has years of investment and use in other contexts. However "ignore" also 
has the wrong sense, because it implies that the computation completes anyway. 
That can be accomplished more easily by simply dropping the promise.

IMO the term cancel(or abort) and ignore are totally different things, the 
former one means “do not continue, stop it right now” and the “stop” state 
should be broadcast to everyone who is interested in the work, while the latter 
means “I don’t care about the result anymore, just play it as you like”, it 
means the async progress can be continued

 This goes back to some of the observations above: you cannot stop it "right 
now" because async notification is not synchronous; indeed the operation may 
already be complete before you stop it. Thus consumers of the result of a 
cancellable request need to be able to handle either successful completion or 
the cancelled state (which just looks like any other error that prevented 
completion).  Attempting broadcast to "everyone" adds complexity and resources 
that are nee

RE: Cancelable promises

2015-02-27 Thread Ron Buckton
AsyncJS (http://github.com/rbuckton/asyncjs) uses a separate abstraction for 
cancellation based on the .NET CancellationTokenSource/CancellationToken types. 
You can find more information about this abstraction in the MSDN documentation 
here: https://msdn.microsoft.com/en-us/library/dd997364(v=vs.110).aspx

Ron

From: John Lenz
Sent: ‎2/‎27/‎2015 8:01 PM
To: Andrea Giammarchi
Cc: public-script-co...@w3.org; 
es-discuss
Subject: Re: Cancelable promises



On Fri, Feb 27, 2015 at 7:49 PM, John Lenz 
mailto:concavel...@gmail.com>> wrote:
Closure Library's promise implementation supports "cancel":

https://github.com/google/closure-library/blob/master/closure/goog/promise/promise.js#L502

A promise is cancelled only if all the "child" promises are also cancelled.

I did not say that correctly, a "parent" promise can be cancelled by a "child" 
it is the only child or all the children cancel.  A parent can alway cancel its 
children (to the children this is simply "reject").  It does add a significant 
amount of complexity to the promise implementation but it is for the most part 
contained there.

I don't believe that "cancel" can be added after the fact and an alternative 
(subclass or otherwise) is needed.


On Thu, Feb 26, 2015 at 11:43 PM, Andrea Giammarchi 
mailto:andrea.giammar...@gmail.com>> wrote:
AFAIK bluebird did:
https://github.com/petkaantonov/bluebird/blob/master/API.md#cancelerror-reason---promise

But I agree once you've made Promises more complex than events ( xhr in this 
case ) nobody wins :-/

Although, specially for fetch or anything network related, there **must** be a 
way to bloody cancel that!

right?


On Fri, Feb 27, 2015 at 7:31 AM, Kevin Smith 
mailto:zenpars...@gmail.com>> wrote:

The discussion on that github issue surrounding promise subclassing makes my 
head spin, especially when it comes to working out how cancelation is supposed 
to flow through a graph of promise dependencies.  We should be wary of adding 
complexity to the core.

The simple way to view the situation is to say that promises are simply 
transparent containers for asynchronous values. Control capabilities should 
therefore be represented by a separate abstraction. This will help keep 
complexity at the edges.

Has any library experimented with the cancelation token approach yet?

On Feb 27, 2015 1:46 AM, "Anne van Kesteren" 
mailto:ann...@annevk.nl>> wrote:
As a heads up, there's some debate around the fetch() API how exactly
request termination should work and how that affects promises:

  https://github.com/slightlyoff/ServiceWorker/issues/625

The WebRTC WG has also been discussing canceling in the context of
terminating a request for permission from the user. I think they
decided to postpone for now until there's a bit more progress on what
cancelable promises means, but I would not expect everyone to wait
forever.


--
https://annevankesteren.nl/
___
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



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


RE: (x) => {foo: bar}

2015-01-05 Thread Ron Buckton
For better or worse, C# avoids this ambiguity through the use of the `new` 
operator:

```
f = x => y => new { x, y };
```

Of course, C# does not support creating an object literal (nee. "anonymous 
type") without `new`, but using `new` here would be generally unambiguous in 
ES7+. Although its legal to write `new {}` in ES today, it currently results in 
a runtime exception.

Ron

Sent from my Windows Phone

From: Brendan Eich
Sent: ‎1/‎5/‎2015 1:01 PM
To: Caitlin Potter
Cc: es-discuss
Subject: Re: (x) => {foo: bar}

Caitlin Potter wrote:
> > You mean replace the footgun with a smaller one, maybe one so small
> it doesn't matter. Saying that the proposal doesn't get rid of the
> footgun means it still remains impossible to write x => {p: x} and not
> get what Frankie and others want: an arrow returning an object. But
> the proposal does fix that footgun.
> >
> > How often do you really want an empty object instead of a block with
> no statements?
>
> Okay, good point about the (lack of) ambiguity in terms of how
> it's interpreted, but what I'm talking about is how it looks like it
> should work. It looks like a function body and an object literal, and
> it doesn't matter which one is used more frequently, because it's
> going to bite people one way or the other.

True. Can't share { as I did in JS and avoid this. Ship sailed long ago.

> Rules about what sorts of statements are allowed as the first
> statement in a block is also going to bite people some times.

Probably not useless labels at the front. Seriously, the change to allow
labels only at top level or else in front of any label-using statement
(and no other) is almost perfectly backward compatible. Stray and unused
labels are latent bugs, even if just minor left-over or misplace noise.

> Because it bites fewer people, there will be fewer people who have
> dealt with it and are able to explain it, so it becomes one of those
> "gotchas" of the language.

Yes, a smaller footgun -- not the same one that started this thread. I
agree it's vexing to have a footgun left, but if it differs in quality
and frequency of misfires, maybe it's worthwhile. Hard to assess.

I also agree KISS favors what we all agreed to do, which was (a) take
arrows into ES6; (b) not pursue block_vs_object_literal after I wrote it
up. But we could revisit (b) and that seems worth some es-discuss overhead.

> This is my personal opinion, but I think the "wrap object literals in
> parentheses for concise bodies" is much simpler to explain to people
> than more complicated rules. Simple is good :>

Your advice is good as far as it goes; it seems not to reach enough
people to avoid a real-world speedbump, from the root message in this
thread.

If the speedbump were caught at compile-time, no big. That it results in
runtime behavior differing from the DWIM intent of the programmer means
latent bugs. Perhaps JSLint, ESHint, etc., will be updated to catch the
bad thing in the field, and that will suffice.

/be
___
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: generator libraries

2015-01-03 Thread Ron Buckton
I wrote http://github.com/rbuckton/queryjs

Sent from my Windows Phone

From: Aaron Powell
Sent: ‎1/‎3/‎2015 6:26 PM
To: 'Mark Volkmann'; 
es-discuss@mozilla.org
Subject: RE: generator libraries

Probably not the one you’re after but I created 
https://github.com/aaronpowell/linq-in-javascript which is a JS Generator 
implementation of .NET’s LINQ API. It has `take` implemented 
(https://github.com/aaronpowell/linq-in-javascript/blob/master/src/linq.js#L325-L354
 and tests 
https://github.com/aaronpowell/linq-in-javascript/blob/master/tests/take.js)


From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Mark 
Volkmann
Sent: Sunday, 4 January 2015 1:19 PM
To: es-discuss@mozilla.org
Subject: generator libraries

Many months ago I ran across a couple of libraries containing utility functions 
for working with generators. I recall one was a "take" function that was used 
to take only the first n values from a a given generator. I'm having trouble 
locating those libraries now. I think one of them was written by a TC39 member. 
Can anyone point me to a library like that?

--
R. Mark Volkmann
Object Computing, Inc.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Elegant way to generate string from tagged template?

2014-12-23 Thread Ron Buckton
For ES6 you could use http://github.com/rbuckton/QueryJS like this:

```
var a = [1,2,3];
var b = ["a", "b", "c"]
var c = Query
  .from(a)
  .zip(b, (a, b) => [a, b])
  .flatMap(a => a)
  .toArray()
  .join("");
```

Ron

Sent from my Windows Phone

From: Brendan Eich
Sent: ‎12/‎23/‎2014 3:39 PM
To: es-discuss@mozilla.org
Subject: Re: Elegant way to generate string from tagged template?

Perhaps the most elegant way is functional composition on arrays, not
string hacking just-so imperative coding: zip composed with flatten and
join. You could even use underscore.js:

http://underscorejs.org/#flatten
http://underscorejs.org/#zip

but JS's OO standard library style prefers method chaining. Array lacks
standard zip and flatten, although concat does one level of flattening:

js> Array.prototype.flatten1 = function () { return [].concat.apply([],
this); };
(function () { return [].concat.apply([], this); })
js> Array.prototype.zip = function (b) { var r = []; var n =
Math.min(this.length, b.length) ; for (var i = 0; i < n; i++)
r.push([this[i], b[i]]); return r; }
(function (b) { var r = []; var n = Math.min(this.length, b.length) ;
for (var i = 0; i < n; i++) r.push([this[i], b[i]]); return r; })
js> ['a', 'b', 'c'].zip([1, 2, 3]).flatten1().join('');
"a1b2c3"

This is just a quick sketch. A real standard library zip would be a bit
more involved, ditto any flatten or flatten1 ;-).

/be
___
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


[ES7+] Promise cancellation (was: Re: Promise-returning delay function)

2014-10-28 Thread Ron Buckton
The direction I've taken around Promise cancellation given the API surface of 
the ES6 Promise has been to use a different object to handle cancellation. This 
approach is similar to the Cooperative Cancelation model used in .NET. The API 
for this looks something like the following (using TypeScript declarations):

```
declare class CancellationTokenSource {
   constructor(...linkedTokens: CancellationToken[]);
   state: string;
   token: CancellationToken;
   cancel(reason?: any): void;
   cancelAfter(delay: number, reason?: any): void;
   close(): void;
}

declare class CancellationToken {
  constructor(source: CancellationTokenSource);
  static none: CancellationToken;
  state: string;
  reason: any;
  throwIfCanceled(): void;
  register(callback: (reason: any) => void): void;
  unregister(callback: (reason: any) => void): void;
}
```

There are several reasons I'm using this approach:
- Separates the concerns of cancellation (CTS/CancellationToken) from 
asynchronous completion (Promise)
- Distinguishes the relationship between the producer and consumer of 
cancellation and completion signals: 
   - A function that performs an asynchronous operation produces the completion 
signal, while the caller receives the signal.
   - The caller produces the cancellation signal, while the function that 
performs the asynchronous operation receives the signal.
- A Promise guarantees all continuations are asynchronous, and will be 
scheduled in a later turn. Cancellation signals must be completed 
synchronously, lest the signal is scheduled after the Promise resolves.
- The producer of a cancellation signal maintains sole control over the ability 
to signal cancellation. Consumers can merely listen for the signal.
- Cancellation signals only propagate up the chain to a Promise producer who 
intentionally listens for the signal.
- Cancellation signals cannot be sent by downstream consumers of a Promise API 
that does not expose its cancellation source.

I've created a gist[1] with a rough reference implementation of 
CTS/CancellationToken, along with examples of many of the above points.

However, this is not truly "cooperative" cancellation, when compared to the 
approach .NET takes. True Cooperative Cancellation would involve Promise 
internals being aware of a CancellationToken, and having a cancellation signal 
affect the state of the Promise automatically in some meaningful way.

Ron

[1] https://gist.github.com/rbuckton/256c4e929f4a097e2c16


From: es-discuss  on behalf of C. Scott Ananian 

Sent: Tuesday, October 28, 2014 11:34 AM
To: Dean Landolt
Cc: Mark S. Miller; Domenic Denicola; Mark Miller; es-discuss@mozilla.org list
Subject: Re: Promise-returning delay function

Dean, your idea is even better as a `Promise` *subclass*.

The subclassed cancellable promises could share a cancel flag, and
throw an exception (or resolve to a different value, whichever you
like better for the API) when the cancel flag is set.  The `then`
method on `CancellablePromise` returns another `CancellablePromise`
(the spec is nicely written this way), and you use `Promise.resolve`
to cast to a standard `Promise` to end the cancellation chain at an
appropriate place.

See the `Promise.bind` implementation in `prfun` for an example of
using subclasses in this way:
https://github.com/cscott/prfun/blob/master/lib/index.js#L518
  --scott

ps. Of course, to be precise, your API would be a factory function
which makes a new subclass of `CancellablePromise` for each cancel
scope, since the Promise spec associates the state with the
constructor identity.  (I had some small issues with the "new subclass
for each X" mechanism in an earlier attempt at creating MonadicPromise
using subclasses, but I think these were ultimately resolved in the
spec---and in that case I was creating a new subclass for each call to
`Promise.resolve`, which was a whole 'nuther kettle of fish.)


On Tue, Oct 28, 2014 at 11:21 AM, Dean Landolt  wrote:
> On Tue, Oct 28, 2014 at 10:41 AM, Andrea Giammarchi
>  wrote:
>>
>> The moment you pass a promise you have no control on who's adding what as
>> callback or errorback which means you have no control over a .reject() or
>> over a .success()
>>
>> .cancel() would eventually keep both queues unresolved so that nothing
>> should happen at all: no error handling, no error happened, and no actions
>> needed ... it's simply canceled.
>>
>> This is the same reason .fetch() API needs also events to work properly
>> (including `progress`) ... you "cannot" base as example typeahead on
>> promises right now 'cause it's a mess to handle since response order is not
>> guaranteed but you need to handle the .cancel() case without telling the
>> user something else went wrong ... what you suggest, a `new Noop()` where
>> `Noop.prototype = Object.create(Error.prototype)` ?
>>
>> And how do you instruct unknown surrounding code that an `if (err
>> instanceof Noop)` should be the first line of ev

Should `Set.prototype.add` return boolean instead of `this`?

2014-10-16 Thread Ron Buckton
??I recall from earlier discussions on this list that the reason 
`Set.prototype.add` returns `this` is to support chained calls to the set, to 
add multiple items, similar to how some libraries like jQuery operate, for 
example:


```

var s = new Set();

s.add(1).add(2).add(3);

```


I have found myself using Set more and more and have found that there are more 
instances where I would rather it return a boolean value, where `true` means 
the value was added to the set, and `false` when the value was not added as it 
already exists.  Without this, I only have two options to detect whether an 
item was added to the set: (a) test using `Set.prototype.has` before adding the 
value, or (b) test using `Set.prototype.size` after adding the value.


# (a) Test using `Set.prototype.has`


```

var s = new Set();

...

if (!s.has(value)) {

  s.add(value);
  // code that executes only for unique values...

}

```


The problem with this solution is that we have to look up the value in the Set 
instance twice. As the Set grows, the cost of this algorithm will always be 
double the cost of the lookup. I imagine implementations can (and likely will) 
attempt to cache recent lookups for performance to mitigate this cost, however 
to a consumer of Set it could appear as if I'm still performing the same lookup 
twice.


# (b) Test using `Set.prototype.size`


```

var s = new Set();

...

var size = s.size;

s.add(value);

if (size < s.size) {
  // code that executes only for unique values...

}

```


This solution removes the double lookup, but feels unnecessarily wordy and 
unintuitive.


# Proposal: `Set.prototype.add` returns Boolean


```

var s = new Set();

...

if (s.add(value)) {

  // code that executes only for unique values
}

```


This seems the most concise and intuitive, and mirrors the 
`Set.prototype.delete` method's return behavior. From the consumer's 
perspective it has the appearance that the lookup only needs to be performed 
once.


Best regards,

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


RE: Proposal: Promise.prototype.Finally

2014-08-18 Thread Ron Buckton
Domenic,

I like the addition that your version of `finally` can itself return a Promise, 
which I hadn't considered (as I hadn't had a need for it myself yet). Is the 
consensus that this won't make it into Promise until at least ES7, and then 
only if there's enough of a call for it?

To be honest, if ES7 has something like async/await then it won't need 
Promise.prototype.finally. Promise.prototype.finally is primarily a feature 
needed for Promises without async/await (e.g. in the ES6 timeframe, or ES7 if 
async/await is deferred to a later revision).

Ron

From: Domenic Denicola 
Sent: Monday, August 18, 2014 3:20 PM
To: Ron Buckton; EcmaScript
Subject: RE: Proposal: Promise.prototype.Finally

Here is the current design for Promise.prototype.finally. I agree it is a 
useful feature.


https://github.com/domenic/promises-unwrapping/issues/18
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Proposal: Promise.prototype.Finally

2014-08-18 Thread Ron Buckton
I created the following gist as a proposal for the addition of a `finally` 
method to the prototype of the Promise constructor, either for ES6 (if such a 
thing is considered valuable and could be fast tracked at this date), or for 
ES7. This method would take in a single callback that would be executed once 
when the antecedent Promise is settled regardless of whether it was fulfilled 
or rejected. If the callback results in a normal completion, the state of the 
antecedent promise would be adopted by the new Promise. However, if the 
callback results in an abrupt completion, the new Promise would be rejected 
with this reason.



You can find more details about this proposal along with amendments to the 
current ES6 working draft below:



[1] https://gist.github.com/rbuckton/66918c8491aa335b003c

[https://avatars2.githubusercontent.com/u/3902892?s=140]

Proposal for addition of Promise.prototype.finally
Proposal for addition of Promise.prototype.finally - Gist is a simple way to 
share snippets of text and code with others.
Read more...




After working heavily with an ES6 Promise shim as of late, I have found such a 
feature would be very valuable. It is possible to patch the ES6 Promise API to 
add such a feature, however it seems like it could be a worthwhile addition 
that could benefit the community until such a time as an `async/await`-like 
syntax is available in ES7+.



Best regards,

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


RE: Overriding Map/etc with get/set hooks?

2014-08-11 Thread Ron Buckton
That should have been @@isValue (Set/Map) and @@isKey (Map.

The downside of having an @@isValue filter is that there are likely still ways 
to get around it (subclasses could define their own, create a new object whose 
[[Prototype]] is an instance of your subclass with its own @@isValue, etc.). 
Too bad there's no way to *really* seal a member.

The options argument could be a definitive solution, though. The Set 
constructor could use the provided options to set an internal slot for a value 
filter. There's possibly still a hole that can't be closed due to 
constructor/prototype tricks.

Ton

Sent from my Windows Phone
____
From: Ron Buckton<mailto:rbuck...@chronicles.org>
Sent: ‎8/‎11/‎2014 6:45 PM
To: Tab Atkins Jr.<mailto:jackalm...@gmail.com>; Allen 
Wirfs-Brock<mailto:al...@wirfs-brock.com>
Cc: Brendan Eich<mailto:bren...@mozilla.com>; 
es-discuss<mailto:es-discuss@mozilla.org>
Subject: RE: Overriding Map/etc with get/set hooks?

Sorry for the short reply here, as I'm not at my PC.

Would having an @@isValue (Map) and @@isKey (Set/Map) work?

Set.prototype[@@isValue] = value => true; // default

Built -in Set operations would check values against @@isValue and throw. You 
can then override it in your subclass and make it non-configurable.

Alternatively, there could be an options argument on the Set constructor where 
you could supply a value filter.

Ron
Sent from my Windows Phone

From: Tab Atkins Jr.<mailto:jackalm...@gmail.com>
Sent: ‎8/‎11/‎2014 5:55 PM
To: Allen Wirfs-Brock<mailto:al...@wirfs-brock.com>
Cc: Brendan Eich<mailto:bren...@mozilla.com>; 
es-discuss<mailto:es-discuss@mozilla.org>
Subject: Re: Overriding Map/etc with get/set hooks?

Restarting this thread, because it's still an issue a year+ on.

In the Font Loading spec <http://dev.w3.org/csswg/css-font-loading/>,
I have a FontFaceSet interface
<http://dev.w3.org/csswg/css-font-loading/#FontFaceSet-interface>,
which is a Set that contains FontFace objects, plus a few other
methods and attributes.

Except that it's not a Set, because I can't subclass Sets reliably.
Instead, I have to duplicate the entire Set interface *as it exists
today*, and have it delegate to a hidden internal Set object.  This
means that when TC39 extends the Set interface, FontFaceSet will have
to be manually updated and bugfixed to contain its own version of the
new methods.  It also means that when authors define new methods on
Set.prototype, they don't apply to FontFaceSet objects unless they
manually copy them to FontFaceSet.prototype as well.

This is obviously bad.  But I can't just directly subclass Set.  If I
do, then authors can do Set.prototype.add(ffset, "hahaha, I'm a
string, not a font face!"), and then the Set is corrupted.  I could,
of course, defensively write all the FFS operations to check each
entry for being a FontFace object first, but that's not quite enough,
because *authors* also have to do this when iterating a FFS.

It's accepted and idiomatic for all sorts of methods in the web
platform to do typechecks on their arguments, and throw errors when
they don't match what's expected.  It's impossible for me to robustly
do this for the Set and Map methods, though.  Can we come up with
something that allows me to enforce these kinds of checks, like I'm
currently doing with my Set-lookalike, and like we do everywhere else
in the entire web platform?

~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: Overriding Map/etc with get/set hooks?

2014-08-11 Thread Ron Buckton
Sorry for the short reply here, as I'm not at my PC.

Would having an @@isValue (Map) and @@isKey (Set/Map) work?

Set.prototype[@@isValue] = value => true; // default

Built -in Set operations would check values against @@isValue and throw. You 
can then override it in your subclass and make it non-configurable.

Alternatively, there could be an options argument on the Set constructor where 
you could supply a value filter.

Ron
Sent from my Windows Phone

From: Tab Atkins Jr.
Sent: ‎8/‎11/‎2014 5:55 PM
To: Allen Wirfs-Brock
Cc: Brendan Eich; 
es-discuss
Subject: Re: Overriding Map/etc with get/set hooks?

Restarting this thread, because it's still an issue a year+ on.

In the Font Loading spec ,
I have a FontFaceSet interface
,
which is a Set that contains FontFace objects, plus a few other
methods and attributes.

Except that it's not a Set, because I can't subclass Sets reliably.
Instead, I have to duplicate the entire Set interface *as it exists
today*, and have it delegate to a hidden internal Set object.  This
means that when TC39 extends the Set interface, FontFaceSet will have
to be manually updated and bugfixed to contain its own version of the
new methods.  It also means that when authors define new methods on
Set.prototype, they don't apply to FontFaceSet objects unless they
manually copy them to FontFaceSet.prototype as well.

This is obviously bad.  But I can't just directly subclass Set.  If I
do, then authors can do Set.prototype.add(ffset, "hahaha, I'm a
string, not a font face!"), and then the Set is corrupted.  I could,
of course, defensively write all the FFS operations to check each
entry for being a FontFace object first, but that's not quite enough,
because *authors* also have to do this when iterating a FFS.

It's accepted and idiomatic for all sorts of methods in the web
platform to do typechecks on their arguments, and throw errors when
they don't match what's expected.  It's impossible for me to robustly
do this for the Set and Map methods, though.  Can we come up with
something that allows me to enforce these kinds of checks, like I'm
currently doing with my Set-lookalike, and like we do everywhere else
in the entire web platform?

~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: ModuleImport

2014-06-24 Thread Ron Buckton
If it is considered legal, then I'd say maybe the default export should be 
named @@default (or a similar symbol) instead.

Ron

Sent from my Windows Phone

From: Calvin Metcalf
Sent: ‎6/‎24/‎2014 5:47 PM
To: Kevin Smith
Cc: EcmaScript
Subject: Re: ModuleImport


Side note: is that legal?  I assumed you wouldn't be able to do that due to 
default being a reserved word.

On Jun 24, 2014 7:53 PM, "Kevin Smith" 
mailto:zenpars...@gmail.com>> wrote:


I don't agree that the changes to the semantics are large, if we're talking 
about simply allowing a single syntactic form for both named and default import 
and Ron's option (A) (where default and named exports can not co-exist... until 
ES7 at least).

But unless you want to rewrite the design, you cannot prevent a default export 
and named exports from co-existing:

function F() { }
export { F as default };  // Named and default



___
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: ModuleImport

2014-06-20 Thread Ron Buckton
> From: John Barton [mailto:johnjbar...@google.com]
> Sent: Friday, June 20, 2014 3:48 PM
> 
> ES6 already has what you want:
> 
> _Named Exports_:
> 
> export var foo = 1;
> 
> _Single Export Object_:
> 
> export var moduleName = {
>   foo: 1,
>   bar: function() {}
> };
> 
> _Single Export Function_:
> 
> export function fName() { }
> 
> 
> And even cooler, the syntax for import is uniform,
> 
> import {foo} from './namedExport';
> 
> import {moduleName} from './singleExportObject';
> 
> import {fName} from './singleExportFunction';
> 

I'm not stating that I specifically "want" anything here, but was rather 
recommending an alternative approach to the single export vs named export 
debate and the removal of the ModuleImport production. David's mail was 
proposing the addition of the following syntax:

```
import * as fs from "fs"
```

This is designed to work around the fact that without ModuleImport, there's no 
simple way to get the module object for the named exports. What you really want 
to write is:

```
import fs from "fs";
```

However, the current semantics don't allow this.  David proposed the new syntax 
as a replacement for ModuleImport. My only issue is that for the end user this 
could be confusing, and its possibly future-hostile for refactoring.

If I have a library today that uses an object literal as a default export in 
Node, and I want to migrate to ES6, the easiest approach is to just replace 
`module.exports =` with `export default`.  My consumers would happy use `import 
foo from "foo"`. If I later want to move to named exports, I would break my 
consumers as they would have to change this to `import * as foo from "foo"`.  
The whole reason for this is that there is a semantic distinction with how a 
default export is handled vs. how named exports are handled.

If I were to use TypeScript's syntax for exports and imports, changing from a 
default export to named exports results in no change for the consumer:

[before.ts]
```
export = {
  foo: 1,
  bar() {}
}
```

[after.ts]
```
export var foo = 1;
export function bar() {}
```

[consumer.ts]
```
import before = require("before");
import after = require("after");
before.foo; // 1
before.bar; // function bar() {}
after.foo // 1
after.bar; // function bar() {}
```

Albeit, TypeScript does not have a Module exotic object, nor does it have 
mutable bindings, nor an ImportList in its import clause. That said, as far as 
the consumer is concerned there's no real distinction between the "default 
export" approach in before.ts and the "named export" approach in after.ts.  We 
have this distinction in ES6 because it was designed that way to support 
mutable bindings and cyclic dependencies. I'm proposing that we come up with 
alternative semantics that preserve that approach while keeping the import 
syntax simple.

As a module consumer, I would constantly need to be aware of whether I need to 
use the `import * as foo from "foo"` syntax or the `import foo from "foo"` 
syntax. Where in Node I would use `require("foo")` for both cases. By changing 
the semantics of ImportDeclaration in ES6 and using a simpler syntax, we could 
would save developers the cognitive cost of determining which import syntax to 
among two very similar forms, as well as supporting the ability for a module 
author to refactor their module from a default export to named exports for the 
single-export-as-object case without affecting their consumers.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: ModuleImport

2014-06-20 Thread Ron Buckton
> -Original Message-

> From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of

> Sébastien Cevey

> Sent: Friday, June 20, 2014 3:46 AM

> To: Axel Rauschmayer

> Cc: es-discuss list

> Subject: Re: ModuleImport

>

> On 20 June 2014 11:39, Axel Rauschmayer  wrote:

> > > The `*' symbol universally represents a glob of "everything", but

> > > when used to import from a module that has multiple exports, you

> > > won't get everything, you will get either the single default export

> > > (if there is

> > > one) or nothing.

> >

> >

> > What gives you that impression? Quoting David’s original email:

> >

> > ```js

> > import * as fs from "fs"; // importing the named exports as an object

> > import Dict from "dict";  // importing a default export, same as ever

> > ```



With all due respect, why is it that we cannot change the specification to 
allow `import name from "module"` for both the default export (for single 
export modules) and the Module object (for multi-named export modules). The 
same question goes for using `import { name as "name" } from "module"` for 
both. As specified, a default export is equivalent to a Module object with a 
"default" property, and as a result requires special handling with respect to 
how it is bound to the _ImportBinding_ in `import name from "module"`. Wouldn't 
it make sense to simplify the syntax and expand the static and runtime 
semantics for imports? Are we sure that the current semantics are the right 
approach that we should shoehorn the syntax into?



Is it imperative for module authors to be able to provide both a default export 
*and* named exports within the same module? From most of the comments in this 
thread, it seems that expected module use falls into two categories:  
Single-export modules and Multi-export modules. Is there a use-case in the wild 
(via ES6 module transpilers) where a single module today uses both a default 
export as well as named exports?



With respect to Node libraries, I often see one of three approaches to 
exporting from a module:



_Named Exports_:

```

exports.foo = 1;

// or

module.exports.foo = 1;

```



_Single Export Object_:

```

module.exports = {

  foo: 1,

  bar: function() {}
}

```



_Single Export Function_:

```

module.exports = function() { }

```



In Node, if you wanted to have a default export that is a function, but also 
have additional exports you would most likely add them as data properties on 
the function:

```

module.exports = function() {}

module.exports.foo = 1;

```



Given that, why not simplify the syntax and semantics to just the following 
three forms:

```

import "module"; // imports the module but does not perform binding

import name from "module"; // imports the module (either the default export or 
a module object with the named exports, see below)

import { name1, name2 as "otherName" } from "module"; // imports members of the 
module.

```



Simplifying this requires the following (approximate) changes in semantics:



* Either (A) a module cannot have *both* a default export and named exports, 
_or_..

* (B) A modules named exports become attached properties of the default export 
if provided.

* If (B), it becomes an runtime error to add a default export after a named 
export, and a runtime error to add a named export if the default export is not 
an Object.

* The ImportBinding (`name` above) becomes bound to a [[Value]] property of an 
(not part of the current spec) Import exotic object.

* When the Module exotic object is loaded, if it has a property named 
"default", that becomes the value of the [[Value]] property of the Import 
exotic object.

* If the Module exotic object does not have a property named "default", the 
Module itself becomes the value of the [[Value]] property of the Import exotic 
object.

* NamedImports now points to bindings to the [[Value]] property of the Import 
exotic object. If you want both a default export and named exports, attach the 
named exports as properties of the default export.



With the above changes, whether you're using a default export or named exports 
becomes transparent to the developer.  If the developer _really_ wants the 
module object, they could fall back to:

```

import "module";

var name = System.get("module"); // Returns the Module object without the 
transformations applied from above.

```



The above is a rough approximation of the semantics changes. If anyone finds 
merit to this proposal, I'll find some time this weekend to write out exactly 
what kind of changes there would need to be in the static and runtime semantics 
in the current spec. The overall goal is to keep the import syntax simple and 
expand the static and runtime semantics to support that simplicity. This 
includes continuing to support the ability to handle cyclic dependencies. 
Engine authors will need to write the code for the import semantics once, while 
the development community will use the import s

RE: Decorators vs Annotations (was April 10 2014 Meeting Notes)

2014-04-15 Thread Ron Buckton
> -Original Message-
> From: Erik Arvidsson [mailto:erik.arvids...@gmail.com]
> Sent: Tuesday, April 15, 2014 8:38 AM
> To: waldron.r...@gmail.com; es-discuss@mozilla.org; Yehuda Katz
> Cc: Ron Buckton
> Subject: Decorators vs Annotations (was April 10 2014 Meeting Notes)
> 
> On Tue Apr 15 2014 at 10:27:23 AM, Rick Waldron  <mailto:waldron.r...@gmail.com> > wrote:
> 
> 
>   ## Decorators for ES7
>   (Yehuda Katz)
> 
>   Slides: (need slides)
> 
>   YK: Presenting aspects of common use cases not yet covered by ES6
> `class`.
> 
>   Knockout.js example (compute the value of a property)
> 
>   WH: Do you want to use functors to produce functions that are per-
> class (i.e. on the prototype) or per-instance?
> 
>   AWB: Per instance wants to be handled in the constructor
> 
>   YUI example (a readonly property)
> 
>   LH/YK: Sometimes you want to say a method is readOnly
> 
>   AWB: No declarative way to describe the per instance state
> 
>   Angular example
> 
>   LH: (explanation) when I declare a class, I also want to register it 
> with
> some other system
> 
>   ES6 Experiments: Angular
> 
>   ```js
>   @NgDirective('[ng-bind]')
>   class NgBind {
> @Inject([Element])
> constructor(element) {
>   this.element = element;
> }
>   }
>   ```
> 
>   AWB: The "@" used to define an annotation
> 
>   JH: Point out that this is inert meta data
> 
> 
> The main use case for Angular is for dependency injection. For that you only
> need meta data.
> 
> Generally decorators are more powerful than annotations since decorators
> can add the meta data as a side effect.
> 
> However, the main issue we ran into with decorators is annotating function
> parameter:
> 
> ```js
> function doSomething(@inject xhr) {
>   ...
> }
> ```
> 
> With decorators it could course be rewritten as:
> ```js
> @annotateParam(inject, 'xhr')
> 
> function doSomething(@inject xhr) {
>   ...
> }
> ```
> 
> Maybe that is sufficient? Maybe that could be done as syntactic sugar?

One options is to use a default instead of a decorator:

```js
function doSomething(xhr = inject('xhr')) {
}
```

Alternatively, a python-like decorator in an argument list position could 
function like this:

```js
// as written:
function doSomething(@inject xhr) {
}

// approximate desugaring:
function doSomething(xhr) {
  xhr = inject(xhr);
}
```

Unfortunately, you lose the ability to use the decorator for pure metadata 
definition and can only use it for mutation during function invocation. 

I experimented with decorators in a fork of TypeScript over a year ago. The 
first run ended up with a very ugly meta type system: 
https://gist.github.com/rbuckton/b2d259d036224a4477f4#metadata-based-param-decorators.

When I was investigating decorators I was looking for a model that worked in 
two ways: 

1. A way to express metadata _about_ something during its definition (akin to 
C# attributes)
2. A way to _mutate/replace_ something during execution

If I wanted to be able to have both the metadata-at-definition and 
mutation-at-execution semantics for argument decorators, I'd need something 
like this:
 
```js
// as written:
function doSometing(@inject xhr) {
}

// approximate desugaring:

// compiler generated identity function
//   using `_doSomething_xhr` here, but in practice this wouldn't be accessible 
as an identifier
var _doSomething_xhr = function(_) { return _; };

function doSomething(xhr) {
  // execute the (possibly mutated/replaced) generated identity function during 
execution of `doSomething`
  xhr = _doSomething_xhr(xhr);
}

// decorate the generated identity function
//   allows for metadata-at-definition semantics
//   `inject` can mutate/replace the identity function which can then affect 
the execution semantics later
_doSomething_xhr = inject(_doSomething_xhr); 
```

The same approach could would for fields in a class (if they are reintroduced 
in ES7):

```js
// as written:
class Sample {
  @inject x;
}

// approximate desugaring:
class Sample {
  constructor() {
this.x = _Sample_x(this.x);
  }
}
var _Sample_x = function(_) { return _; };
_Sample_x = inject(_Sample_x);
```

Of course, this approach has the obvious downside of allocating a function for 
every argument/field that has a decorator.

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


RE: Promise.cast and Promise.resolve

2014-02-05 Thread Ron Buckton
Perhaps the unwrapping behavior of .then could be specified as an optional 
argument in the Promise constructor and .resolve methods.  The default behavior 
is the current standard (i.e. .then auto-unwraps), but a different behavior 
could be specified:

```
var unwrapPromise1 = Promise.resolve(1);
var unwrapPromise2 = Promise.resolve(unwrapPromise);
unwrapPromise2.then(value => { 
  assert(value === 1); // unwraps
}) 

var flatPromise1 = Promise.resolve(1, "flat"); // or some other indicator of a 
monadic promise
var flatPromise2 = Promise.resolve(flatPromise1, "flat"); 
flatPromise2.then(value => { 
  assert(value === flatPromise1);
}) 

var mixedPromise = unwrapPromise2.then(value => flatPromise2);
mixedPromise.then(value => { 
  assert(value === flatPromise1); // mixedPromise's unwrapping stops at 
flatPromise1 as it starts to unwrap flatPromise2 but stops unwrapping due to 
the defined behavior. 
  return value;
}).then(value => {
  assert(value === flatPromise1); // Since the previous .then was unwrapped 
into a "flat" promise, chained .then calls remain "flat". 
});
```

Basically, unwrapping of .then stops once the monadic behavior is reached.  
This would work for Promise.all/Promise.race as well since they could respect 
this behavior.  This has the added benefit of specifying Promises with a 
minimal API surface that auto-unwrap for ES6, but add optional arguments to the 
constructor and .resolve for ES7 or later to specify this behavior. As far as 
the Promise consumer is concerned, when they use .then, they will get the 
result the Promise producer expects them to get (the final underlying value in 
the common use case, or a possible promise in the monadic case).  The API 
surface area does not change, and monadic promises become an opt-in for those 
that need the specialized case.

Best regards,
Ron

> -Original Message-
> From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of
> Brendan Eich
> Sent: Wednesday, February 5, 2014 7:46 AM
> To: Quildreen Motta
> Cc: Mark S. Miller; EcmaScript
> Subject: Re: Promise.cast and Promise.resolve
> 
> Quildreen Motta wrote:
> > but as with other parts of JavaScript, the simpler, orthogonal
> > primitives are not available for users to derive more complex
> > functionality from easily.
> 
> So true. JS is like a mini-toolkit of three-tool Swiss Army Knife
> (functions) with constructor and closure tools as well as the big first-class
> function edged tool; and super-caulk (objects) usable in a pinch as adhesive
> as well as sealant. Kind of what you want when you are traveling light, in a
> hurry running from zombies, no time to get a proper toolbox.
> 
> Part of TC39's work has been decomposing some of the multi-tools into new
> forms that do one thing well (arrow functions are my favorite in this regard).
> But it is both hard to justify the effort, and actually a lot of effort, to
> decompose fully in all cases.
> 
> Still I agree with Paolo. If we had functional (even value-like, featureless,
> then-able only via a special form, as in E) Futures, we could rebuild Promises
> on them and let Promises remain the library they've always been.
> 
> /be
> ___
> 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: transpiling ES6 generator functions to ES5: what next?

2014-01-14 Thread Ron Buckton
I haven't had the opportunity to look at the transpiler, but I did something 
similar in a fork of TypeScript 0.8.3 on CodePlex a little over a year ago 
(back when StopIteration was part of the spec.) I've been meaning to update it 
to the current version, so I'll run it through the test suite below when its 
ready.

Sent from my Windows Phone

From: David Bruant
Sent: ‎1/‎14/‎2014 10:01 AM
To: Ben Newman; 
es-discuss@mozilla.org
Subject: Re: transpiling ES6 generator functions to ES5: what next?

Hi Ben,

Sorry for the very late response.
This is quite an interesting work, thanks for sharing!
I'm particularly interested in your test suite [1] which is impressive.

This is making me realize that generators are fully compilable (efficiently 
from what I can see) into ES5 and makes me wonder if the current generators 
specificities are worth it. Very specifically, do we really need 
Generator.prototype [ @@toStringTag ] === "Generator" ?
>From an author point of view, I don't really see in which situation this 
>information could matter. As a comparison, functions generated after the class 
>syntax do not have an @@toStringTag to "Class".
Generators would just be sugar to write iterators (+ .throw)


Le 03/11/2013 21:55, Ben Newman a écrit :

  *   Given that this tool will become obsolete as more and more engines 
implement ES6 generator functions, how can we maximize its value in the 
meantime? Are there grey areas in the draft spec that can be illuminated? 
Should I spend my time implementing (or getting others to implement) await 
syntax and/or control-flow libraries that leverage generator syntax?

You can most certainly experiment with await syntax and share what you've 
learned.
Are there any test cases that you've written and you feel like the expected 
spec behavior is odd or unintuitive in some aspect?


  *   How would you design a system that selectively delivers transpiled code 
to ES5-capable browsers and native generator code to ES6-capable browsers, so 
that end users will benefit immediately when they upgrade to a browser with 
native support for generators?

Since there is no semantic difference between the ES6 and your compiled 
version, it's unlikely the users will see a difference at all (not even sure 
the perf is that much different).

But if you really want to try there are different options with different  
downsides.
1) Server-side UA sniffing. You get the User-Agent header, infer which browser 
it is and decide which version you should be sending. Send the ES5 version when 
you don't know the UA (safe default)

Downsides:
* if a browser changes its header, you may be sending the wrong version. This 
is a problem when you're sending the ES6 version to a non-ES6 browser (which 
admittedly should be a very rare case)
* You need to update the list of ES6 User-Agent strings as new browsers arrive

2) Send a feature-detection JS snippet on the client which will decide which 
version to load.

Downside:
* having to wait until this snippet is executed to start code download (or one 
extra round-trip if code was originally inlined)

3) send compiler to the client-side

Downside:
* more code

Personally, I'd go for sending the ES5 version to everyone. My second choice 
would be 1), but I guess it depends on the requirements.

David

[1] https://github.com/facebook/regenerator/blob/master/test/tests.es6.js
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Promises: final steps

2013-09-05 Thread Ron Buckton
Tasks in C# throw the recorded exception when the Task is finalized by the GC 
if it hasn't been handled by user code, though I don't know if something 
similar could be supported for ES7 Promises nor whether or not that makes sense 
for ES7 promises either.

Having Promise rejections hold on to unhandled rejections can be mitigated 
either with eventual language support around Promises (either an 
async/await-style operator, or the ! operator in the strawman) or through a 
userland approach by way of trampoline functions. In the C# world with 
async/await, exceptions are thrown at the site of the "await" keyword when the 
operand becomes Faulted. In general this alleviates many of the issues around 
Tasks swallowing exceptions, although there are still a few cases where you 
have to take care around exception handling (e.g. an async method that returns 
`void` rather than `Task` or `Task`, as it cannot be awaited). 

Promises in the short-term may have some deficiencies until there is a syntax 
defined for asynchronous functions. That said, I'm fine with not having 
`Promise#done`, as useful as it is, as long as there is a reliable and well 
defined mechanism to raise the rejection to the host if needed (outside of 
reaching out to setImmediate to throw the exception, as it may not be obvious 
to consumers of the Promise API).

Ron

> -Original Message-
> From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of
> medikoo
> Sent: Thursday, September 5, 2013 2:46 AM
> To: es-discuss@mozilla.org
> Subject: Re: Promises: final steps
> 
> While I can agree that "monitor" feature (that's proposed instead of `done`) 
> has
> some benefits, I see it only as an aid for developers that are inexperienced 
> with
> promises, or as a fallback for those experienced.
> It looks more as a smart add-on, which to be complete can't be implemented in
> plain JavaScript, is implementation specific and should be treated as 
> optional.
> 
> What's more important it still doesn't provide developer with full control of
> error handling on JavaScript level and that can be achieved only with `done`.
> 
> I have problems understanding why such complex and not natural feature is
> favored over something so simple and straightforward.
> 
> 
> 
> 
> --
> View this message in context: http://mozilla.6506.n7.nabble.com/Promises-
> final-steps-tp290303p290518.html
> Sent from the Mozilla - ECMAScript 4 discussion mailing list archive at
> Nabble.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: Letting RegExp method return something iterable?

2013-08-28 Thread Ron Buckton
The advantage of a lazy execAll, is the ability to break out of the for..of 
loop without the need to continue to traverse the input string looking for 
matches. This is the same advantage that the `while(m = re.exec())` has going 
for it. You can always be greedy by using Array.from or an array comprehension 
if execAll is lazy, but you are back to using a while loop if execAll is greedy 
and you want lazy matching, which limits its usefulness in some scenarios.

Ron

Sent from my Windows Phone

From: Forbes Lindesay
Sent: ‎8/‎28/‎2013 4:55 PM
To: Andrea Giammarchi
Cc: Brendan Eich; es-discuss 
list; Erik 
Arvidsson
Subject: RE: Letting RegExp method return something iterable?

Right, I don’t care whether it’s lazy.  I only care that it exists.  Nobody’s 
crying out for a lazy version of string split (at least not yet anyway).  I 
have had the issue of needing to loop over all the matches that a regular 
expression has.  It is a common, recurring issue that many developers face.

Let’s move on from whether it should exist (clearly it should) and stick to 
whether it should be an array, or lazy.  Does anyone have a strong opinion 
either way?  The fact that all our regular expression iteration thus far has 
been lazy to me suggests this probably should be too, but maybe it would be 
simpler if it returned an array.  I really hope someone will chime in on this.

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


RE: Killing `Promise.fulfill`

2013-08-19 Thread Ron Buckton
Promise.fulfill/PromiseSource#fulfill made sense when there was no unwrap on 
the input side of Promise#then:

*then:*
```js
var foreverPending = new Promise(() => {});
Promise.fulfill(foreverPending).then(x => assert(x === foreverPending))
Promise.resolve(foreverPending).then(() => { /* never reached */ });
```

*now*
```js
var foreverPending = new Promise(() => {});
Promise.fulfill(foreverPending).flatMap(x => assert(x === foreverPending));
Promise.fulfill(foreverPending).then(() => { /* never reached */ });
```

With all the changes to Promise (addition of Promise#flatMap, recursive unwrap 
on input side of Promise#then, etc.), it does seem that fulfill's use case has 
become a bit muddled. I'll admit to still being partial to the earlier design 
(fulfill/resolve/reject, adopt without recursive unwrap/flattening) as it was a 
much simpler and more straightforward API.

Ron


> -Original Message-
> From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of
> Domenic Denicola
> Sent: Monday, August 19, 2013 11:13 AM
> To: es-discuss@mozilla.org
> Subject: Killing `Promise.fulfill`
> 
> In https://mail.mozilla.org/pipermail/es-discuss/2013-August/032724.html (plus
> following errata) I created the following promise:
> 
> ```js
> var foreverPending = new Promise(() => {}); var acceptedButNotResolved =
> Promise.fulfill(foreverPending); ```
> 
> This brings up the horrible point that `Promise.fulfill(foreverPending)` 
> creates a
> promise that is pending, not fulfilled. Argh!
> 
> There's also the issue that the distinction between accepted and resolved is 
> not
> very useful. They are only distinguishable by flatMap, not by then, and the
> distinction that flatMap can make is confusing and doesn't seem to buy
> anything.
> 
> Tab and I think the solution to this is to:
> 
> - Kill `Promise.fulfill`, and of course also the `fulfill` option to the 
> promise
> initializer.
> - Change `flatMap` to operate on resolved values, so that
> `Promise.resolve(foreverPending).flatMap(x => assert(x === foreverPending))`
> works.
> 
> This removes the "accepted" state entirely. It means `flatMap` effectively
> becomes a method for peeking into resolved promises and seeing what they
> are resolved to.
> 
> This also opens up the possibility of making the promise constructor go back 
> to
> `new Promise((resolve, reject) => ...)`, in alignment with Promises/A+ and
> symmetric with `then`. The current asymmetric choice of `new Promise(({
> resolve, reject, fulfill }) => ...)` has always felt unfortunate to me.
> 
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: setImmediate

2013-08-09 Thread Ron Buckton
For promises using microtasks, one possibility I've been experimenting with in 
my polyfill is a Promise.yield() method that returns a Promise that resolves 
after the next time the UI thread gets a chance to drain its event queue 
(either through requestAnimationFrame or setTimeout).

While it works better with async/await or generators+trampoline, it still works 
with Promise#then (and Promise#flatMap).  It doesn't prevent developers from 
writing bad code, but it does provide a way to break out of the microtask 
scheduler.

Also, unless it breaks an invariant or expectation, would it be useful to have 
microtasks periodically and/or randomly yield to the event queue to allow the 
UI to drain its events? There could also be a (albeit probably better named) 
nextMicrotaskWillYield() API that could be called to have some foreknowledge as 
to whether future microtasks scheduled within the current microtask will be 
delayed until after the browser can process tasks or the event queue.

Ron

Sent from my Windows Phone

From: Jorge Chamorro
Sent: ‎8/‎9/‎2013 9:50 AM
To: David Bruant
Cc: EcmaScript
Subject: Re: setImmediate

On 08/08/2013, at 15:55, David Bruant wrote:

> This is not a "Trying to protect us from ourselves" situation. This is a 
> "browser trying to protect users from any sort of abuse" situation. For while 
> loops, they implemented the "script takes too long" dialog. For mistakenly 
> infinitely nested too short setTimeouts, they implemented 4ms clamping.
> If browsers can't have mitigation strategies when features are abused, we 
> will run in the same situations than before.
>
> As a JS dev, I want the same features than you. Now, how do browsers make 
> sure this doesn't drain users battery in case of misuse? (I don't have an 
> answer yet)

I think that it can't be avoided. A program, in the middle a longish operation, 
*must* yield to the event loop to avoid events starvation and/or to force 
redraws, so there *must* be a way to do so, and it *must* be *fast* (without 
4ms clampings).

Yes, there are malicious sites and there are silly programmers to drain your 
batteries, but there are also 100% legit reasons to spin the event loop...

I would put in the browsers a cpu hog/battery drain dial/indicator per page, so 
that the users could at least see it and act accordingly (they'll soon learn 
why that's important).

I for one have already uninstalled lots of iPhone apps, just because they 
drained my batteries too fast.

Also, the original "classic" MacOS had an EventAvail() call to let the program 
know if there were any events pending, in a program in a busy loop this helps 
decide whether it's time to yield or not.
--
( Jorge )();
___
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: generators vs forEach

2013-07-15 Thread Ron Buckton
I assume you are referring to something like Q.async/Q.spawn to turn the 
generator into an async function using promises?

Sent from my Windows Phone

From: Ron Buckton<mailto:rbuck...@chronicles.org>
Sent: ‎7/‎15/‎2013 5:02 PM
To: Bruno Jouhier<mailto:bjouh...@gmail.com>; 
es-discuss<mailto:es-discuss@mozilla.org>
Subject: RE: generators vs forEach

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

Sent from my Windows Phone

From: Bruno Jouhier<mailto:bjouh...@gmail.com>
Sent: ‎7/‎15/‎2013 4:12 PM
To: es-discuss<mailto:es-discuss@mozilla.org>
Subject: Re: generators vs forEach

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

With the C# async/await notation:

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

With this you can write:

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

and you can call it as:

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

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

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

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

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

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

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

Bruno

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

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


RE: generators vs forEach

2013-07-15 Thread Ron Buckton
Bruno, wouldn't yield* work here to delegate the inner yields?

Sent from my Windows Phone

From: Bruno Jouhier
Sent: ‎7/‎15/‎2013 4:12 PM
To: es-discuss
Subject: Re: generators vs forEach

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

With the C# async/await notation:

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

With this you can write:

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

and you can call it as:

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

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

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

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

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

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

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

Bruno

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

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


RE: Why does Array.from also take a mapFn?

2013-06-30 Thread Ron Buckton
Couldn't you just do:

var squaredSmalls = Int16Array.from((v*v for v of smalls));

Or is the allocation of a generator  expensive enough to warrant the mapFn 
argument? Alternatively, is it the need to support a map on a non-iterable 
"array-like"?

Ron

Sent from my Windows Phone

From: Tab Atkins Jr.
Sent: ‎6/‎24/‎2013 1:28 PM
To: Domenic Denicola
Cc: es-discuss
Subject: Re: Why does Array.from also take a mapFn?

On Mon, Jun 24, 2013 at 12:55 PM, Domenic Denicola
 wrote:
> Thanks Allen. The
>
>> ```js
>> var squaredSmalls_try2= Int16Array.from(smalls.map(v=> v*v));   // still no 
>> good, because intermediate array is Int8Array
>> ```
>
> example certainly clears it up for me. Tricky stuff.
>
> I was going to write "it's still a bit weird to me that we overload 
> `Array.from` with the mapping functionality", but then I realized this is 
> only weird because of my preconceptions about `Array.from` dating back from 
> when we first discussed it on-list.
>
> Taken on its own, without any historical bias, I think it's fine for 
> `Array.from`, and more importantly `Int16Array.from` etc., to take a mapping 
> function. You derive a new `Int16Array` "from" another iterable, optionally 
> via some rule. Makes sense!

Yup; in other words, Array.from is just the type-converting Array#map
(defaulting its callback to the identity function).

~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: Where'd Promise#done go?

2013-06-18 Thread Ron Buckton
I've often looked at Promise#then() as sugar over Promise#done() for something 
like:

```js
Promise.prototype.then = function(resolve, reject) {
  return new Promise(resolver => {
this.done(
  value => {
try {
  resolver.resolve(resolve ? resolve(value) : value);
}
catch (e) {
  resolver.reject(e);
}
  },
  err => {
try {
  resolver.resolve(reject ? reject(value) : value);
}
catch (e) {
  resolver.reject(e);
}
  });
  });
}
```

Promise#done() doesn't have the overhead that Promie#then does (allocating a 
new chained Promise), so it is more efficient if you don't need to chain. It 
feels easier to be more explicit with done then without, since to polyfill done 
requires calling something like setImmediate to raise the error to the 
engine/window.onerror, since throwing it in the reject handler would just 
result in a new rejected Promise.

If we had an 'await' keyword I might find the need for done to be less 
important, as it would be easy to write "await p" to bubble the exception to 
user code. Although, 'await' would also be more efficient with 'done' rather 
than 'then'.

If Promise#done is out, a polyfill could just have an array of unhandled 
exceptions that could be analyzed programmatically in user code or via the 
console.

Sent from Windows Mail

From: Mark S. Miller
Sent: ?Tuesday?, ?June? ?18?, ?2013 ?8?:?14? ?PM
To: Domenic Denicola
Cc: es-discuss

On Tue, Jun 18, 2013 at 8:11 PM, Domenic Denicola 
mailto:dome...@domenicdenicola.com>> wrote:
From: Mark S. Miller [mailto:erig...@google.com]

> I don't understand this. I am onboard with 
> `console.unhandledRejection`/`console.rejectionHandled` and all that for 
> better logging, and with using WeakRef notification to improve the logging 
> yet further. But I don't see how any of this can substitute for the need that 
> .done() serves. I think we will still need .done() in ES7 promises.

While I think I see what you're getting at,

What do you think I'm getting at? ;)


 let me play devil's advocate for a bit to draw this out more clearly. Using 
the sample code from 
https://github.com/promises-aplus/unhandled-rejections-spec/issues/1:

```js
var rejectPromise;
var promise = new Promise((resolve, reject) => rejectPromise = reject);

promise.then(() => console.log("I only attached a handler for fulfillment"));
// All is OK (A)

rejectPromise(promise, new Error("who handles me?"));
// Nobody sees the error! Oh no, maybe we should crash here? (B)

setTimeout(function () {
promise.then(undefined, (err) =>console.error("I got it!", err));
// But if we crashed there, then how would this code ever get run? (C)
}, 5000);
```

Using a `done`-less promise implementation with a unhandled rejections console, 
we have the flow that:

1. At line (A), all is fine, and the unhandled rejections console is empty.
2. At line (B), the unhandled rejections console contains `Errror: "who handles 
me?"`. This remains true for the next five seconds.
3. At line (C), after five seconds have passed, the unhandled rejections 
console becomes yet again empty.

This seems to neatly solve the problem without `done`, at least in my 
devil's-advocate world. Where's the problem? :)



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


Re: The Paradox of Partial Parametricity

2013-05-27 Thread Ron Buckton
My apologies, I've seen three use cases. The third use case being the ability 
to send progress notifications.

Sent from Windows Mail

From: Ron Buckton
Sent: ‎Monday‎, ‎May‎ ‎27‎, ‎2013 ‎12‎:‎47‎ ‎PM
To: Andreas Rossberg, Tom Van Cutsem
Cc: Mark S. Miller, Brendan Eich, es-discuss

Are there a fixed number of use cases for promise subclasses? I’ve seen 
discussions about two possibilities referred to on this list, specifically a 
lazy-promise and a cancellable promise. I wonder if these two capabilities 
should instead be part of the Promise/Future API and not have subclasses 
promises. High-order operations like Q.all/Future.every will cause the subclass 
to be lost to the resulting operation.

I do agree with the earlier discussion that adding a cancel method to a promise 
can expose too much to the consumer, allowing multiple consumers of the same 
promise the ability to cancel the root. I have been experimenting [1] with 
supplying a cancellation signal from outside the promise that can be provided 
to the various API’s (as an optional argument to the constructor and to 
then/done) to allow for cancellation but respect the separation of 
responsibilities between a promise and its creator. This makes cancellation 
optional, but fully baked into the API, as well as allowing the promise to 
fully cooperate with cancellation internally.

In a similar way we could enable lazy initialization of the promise via an 
argument to the constructor. Are there other use cases for promise subclasses?

Not subclassing promise doesn't prevent it from being a first-class object, 
just as how today you can’t subclass Function, yet functions are first class.

Ron

[1] http://github.com/rbuckton/promisejs

Note: this is roughly based off of the DOM Futures spec with some non-spec 
additions, and performs auto-lift and single unwrap as discussed in an earlier 
thread.

Sent from Windows Mail

From: Tom Van Cutsem
Sent: ‎Monday‎, ‎May‎ ‎27‎, ‎2013 ‎8‎:‎09‎ ‎AM
To: Andreas Rossberg
Cc: Mark S. Miller, Brendan Eich, es-discuss

2013/5/27 Andreas Rossberg mailto:rossb...@google.com>>
On 27 May 2013 15:30, Tom Van Cutsem 
mailto:tomvc...@gmail.com>> wr
> What the discussion at last week's TC39 meeting clarified for me is the
> following:
>
> - Promises are primarily a control-flow abstraction.
> - Sometimes, they are also used as a data-abstraction (i.e. as a container
> in their own right, wrapping an arbitrary payload).
> - All of the subtle problems discussed in these threads only start to arise
> when these two use cases of promises are being mixed, e.g. a
> promise-as-data-container being mistaken for a
> promise-as-control-abstraction. This rarely happens in application code, but
> may happen in generic library code.

Well, the gist of higher-order languages is that control flow
abstractions _are_ data. For example, that's the defining
characteristics of first-class functions. And while most functions
won't be used in a first-class manner (and most programmers probably
don't think about them that way), the ability to do so gives great
power -- as JavaScript demonstrates very well.

Futures/promises are an abstraction for first-class synchronisation.
For the same reason you sometimes want to store or pass back & forth
functions, you will sometimes want to store or pass promises. Not
being able to combine those abstractions freely and transparently
would arbitrarily limit their power, and practically demote promises
to second-class status.

I agree with everything you said, but I fail to see why Q-style promises would 
become second-class. I have enjoyed writing and working with higher-order 
combinators like Q.all, which creates a promise for an array of promises. Your 
text above would seem to imply that writing or using such combinators would 
somehow be hampered by the recursive flattening, but I have never bumped into 
this issue. I think the reason is that when promises are used as data in 
combinators like Q.all, the composite abstraction as a whole remains a 
control-flow abstraction.

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


Re: The Paradox of Partial Parametricity

2013-05-27 Thread Ron Buckton
Are there a fixed number of use cases for promise subclasses? I've seen 
discussions about two possibilities referred to on this list, specifically a 
lazy-promise and a cancellable promise. I wonder if these two capabilities 
should instead be part of the Promise/Future API and not have subclasses 
promises. High-order operations like Q.all/Future.every will cause the subclass 
to be lost to the resulting operation.

I do agree with the earlier discussion that adding a cancel method to a promise 
can expose too much to the consumer, allowing multiple consumers of the same 
promise the ability to cancel the root. I have been experimenting [1] with 
supplying a cancellation signal from outside the promise that can be provided 
to the various API's (as an optional argument to the constructor and to 
then/done) to allow for cancellation but respect the separation of 
responsibilities between a promise and its creator. This makes cancellation 
optional, but fully baked into the API, as well as allowing the promise to 
fully cooperate with cancellation internally.

In a similar way we could enable lazy initialization of the promise via an 
argument to the constructor. Are there other use cases for promise subclasses?

Not subclassing promise doesn't prevent it from being a first-class object, 
just as how today you can't subclass Function, yet functions are first class.

Ron

[1] http://github.com/rbuckton/promisejs

Note: this is roughly based off of the DOM Futures spec with some non-spec 
additions, and performs auto-lift and single unwrap as discussed in an earlier 
thread.

Sent from Windows Mail

From: Tom Van Cutsem
Sent: ?Monday?, ?May? ?27?, ?2013 ?8?:?09? ?AM
To: Andreas Rossberg
Cc: Mark S. Miller, Brendan Eich, es-discuss

2013/5/27 Andreas Rossberg mailto:rossb...@google.com>>
On 27 May 2013 15:30, Tom Van Cutsem 
mailto:tomvc...@gmail.com>> wr
> What the discussion at last week's TC39 meeting clarified for me is the
> following:
>
> - Promises are primarily a control-flow abstraction.
> - Sometimes, they are also used as a data-abstraction (i.e. as a container
> in their own right, wrapping an arbitrary payload).
> - All of the subtle problems discussed in these threads only start to arise
> when these two use cases of promises are being mixed, e.g. a
> promise-as-data-container being mistaken for a
> promise-as-control-abstraction. This rarely happens in application code, but
> may happen in generic library code.

Well, the gist of higher-order languages is that control flow
abstractions _are_ data. For example, that's the defining
characteristics of first-class functions. And while most functions
won't be used in a first-class manner (and most programmers probably
don't think about them that way), the ability to do so gives great
power -- as JavaScript demonstrates very well.

Futures/promises are an abstraction for first-class synchronisation.
For the same reason you sometimes want to store or pass back & forth
functions, you will sometimes want to store or pass promises. Not
being able to combine those abstractions freely and transparently
would arbitrarily limit their power, and practically demote promises
to second-class status.

I agree with everything you said, but I fail to see why Q-style promises would 
become second-class. I have enjoyed writing and working with higher-order 
combinators like Q.all, which creates a promise for an array of promises. Your 
text above would seem to imply that writing or using such combinators would 
somehow be hampered by the recursive flattening, but I have never bumped into 
this issue. I think the reason is that when promises are used as data in 
combinators like Q.all, the composite abstraction as a whole remains a 
control-flow abstraction.

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


RE: Non-generic traps for non-generic objects (was: Overriding Map/etc with get/set hooks?)

2013-05-24 Thread Ron Buckton
Another way to look at this is that there is no way to prevent a caller from 
using methods from the superclass on a subclass. In other OO languages, its 
much harder (or nearly impossible depending on the language) to forcibly call a 
superclass method against a subclass that has been overridden by the subclass. 

Tab wouldn't have this issue if there were a way to prevent an external caller 
from executing Map.prototype.set.call(mapSubclass) if the mapSubclass overrides 
`set`.

Ron

From: es-discuss-boun...@mozilla.org on behalf of Tab Atkins Jr.
Sent: Friday, May 24, 2013 5:08 PM
To: Jason Orendorff
Cc: EcmaScript
Subject: Re: Non-generic traps for non-generic objects (was: Overriding Map/etc 
with get/set hooks?)

On Fri, May 24, 2013 at 11:53 AM, Jason Orendorff
 wrote:
> On Fri, May 24, 2013 at 12:02 PM, Tab Atkins Jr. 
> wrote:
>> On Fri, May 24, 2013 at 9:27 AM, Jason Orendorff
>>  wrote:
>> > Counterproposal: address this in WebIDL. Add a magic [Maplike] tag that
>> > means something like: [...]
>>
>> [...] It's not the *best* solution, because the easy magic is only there
>> for
>>
>> spec authors, but it's the best so far.
>
>
> I see your point. I think this is a case where spec authors definitely have
> a problem, but JS programmers will not sweat it that much.
>
> In JS it's just so easy:  https://gist.github.com/jorendorff/5645591

That's only "easy" because we can assume that authors will manually
adjust their code when we add more Map methods, or if they want to add
their *own* Map methods.  That's the exact thing I'm complaining
about, except that we can't assume that specs will get updated in this
way.

~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: Overriding Map/etc with get/set hooks?

2013-05-21 Thread Ron Buckton
What if the default Map prototype had a configurable but non-writable data 
property for a @@coerceKey symbol that pointed to a default coercion function. 
You could subclass Map and provide your own @@coerceKey implementation. Then 
Map.prototype.set.call() would be forced to run the custom coercion function.

A @@coerceKey override could be used to coerce keys from one type to another, 
or to provide key validation if you want keys in a specific format. By 
providing a default implementation that is basically an identity function, you 
maintain the same current expectations for Map. This then gives developers the 
ability to further customize the behavior of Map in subclasses, giving the 
class more flexibility.

If that were the case, there could also be a @@coerceValue symbol on 
Map.prototype as well as Set.prototype. Possibly even Array.prototype as well 
for Array subclasses, as a means of limiting array contents to a specific type. 
The coercion functions could also be used to allow a subclass to Mark itself as 
read-only and throw on attempts at modification. Default implementations could 
verify whether the coercion function has changed from the default and skip the 
coercion calls as a performance optimization.

Ron

Sent from Windows Mail

From: Tab Atkins Jr.
Sent: ‎Tuesday‎, ‎May‎ ‎21‎, ‎2013 ‎10‎:‎53‎ ‎AM
To: Sam Tobin-Hochstadt
Cc: Brendan Eich, es-discuss

On Tue, May 21, 2013 at 7:19 AM, Sam Tobin-Hochstadt  wrote:
> On Tue, May 21, 2013 at 6:52 AM, Anne van Kesteren  wrote:
>> On Tue, May 21, 2013 at 12:19 PM, Brendan Eich  wrote:
>>> Of course, coercing key type makes the API not Map. So if the
>>> bi-directionality is important, this would be a custom Map-like class.
>>
>> I guess I also do not really get this. Sure JavaScript does not have a
>> type system (yet?), but it seems that placing restrictions / coercion
>> on input does not invalidate any of the properties of a map other than
>> that there's a restriction on what goes in the map. To me that seems
>> very much like a subset of a map and all generic functionality written
>> around maps would work on such a map.
>
> The following function returns true for all Maps M, Strings k, and JS values 
> v:
>
> function check(M, k, v) {
>M.set(k,v);
>return (v === M.get(k));
> }
>
> In fact, this is the essence of what Maps are about.  Your proposal
> doesn't have this property. Therefore, it shouldn't be a Map.

Within the type constraints we enforce, this is maintained.  That is,
if you use string keys and values, it maintains *all* of the Map
invariants.  If you use non-string keys or values, we coerce to a
string first, so the invariants may not hold in all circumstances.
That's the point of coercion.

This argument is like saying that, if "p.foo = obj; p.foo === obj;"
isn't maintained, then "p" isn't an Object and should be something
else.  In reality, we're completely fine with "foo" being a getter or
setter with arbitrary effects; in particular, it can apply coercion
rules, which is rather common on the web.

If TC39 isn't going to allow us to ever use *any* of the built-in
collection classes just because we have type restrictions we need to
enforce, that'll be a pretty raw deal for authors.  It'll just mean we
continue with our "custom, shitty, incompatible versions of all your
standard collections" thing that we've been doing for some time. (And
never doubt, for each collection you have, we'll have N slightly
incompatible versions, where N is proportional to the number of specs
that use something like the collection.)

> The analogy to NodeList is actually valuable -- NodeLists are pretty
> different from Arrays, but some of the array generics work on them. If
> the problem is that the Map functions should be more generic, that's
> something that could be fixed, but that doesn't mean we should pretend
> that things are maps when they aren't.

Making the methods more generic won't help much (though it would
probably help *slightly*) - the problem is that the methods *aren't on
the objects*.  Try to guess the relative numbers of people who do
"Array.prototype.forEach.call(arrayLike, ...)" versus the numbers who
just do a quick "Array.prototype.slice.call(arrayLike)" at the
beginning and then rejoice at having a real Array to use.

We need to fix this "type coercion means it's not one of ours"
problem, now.  It's not good for authors or for the platform as a
whole.

~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: The Paradox of Partial Parametricity

2013-05-10 Thread Ron Buckton
Following Tab's comments on the a Promise monad, I prototyped a Future library 
based on DOM Future using TypeScript. Since TS has no concept of a union type, 
I'm using TS overloads to approximate the Ref union type example. It has 
roughly the following API:

```ts
class FutureResolver {
  accept(value: T): void;
  resolve(value: Future): void;
  resolve(value: T): void;
  reject(value: any): void;
}

class Future {
  constructor(init: (resolver: FutureResolver) => void);

  // unconditional lift
  static accept(value: TResult): Future;

  // autolift
  static resolve(value: TResult): Future;
  static resolve(value: Future): Future;

  static reject(value: any): Future;

  // assimilation of thenables, similar to `Q()`. Assimilation stops at the 
first `Future`
  static from(value: any): Future;

  // autolifting then.
  // for `p.map` like operation, `resolve` should return `Future.accept(u)`
  // for `p.flatMap` like operation, `resolve` can return u or 
`Future.resolve(u)`, but no error is thrown
  then(resolve: (value: T) => Future, reject: (value: any) => 
Future): Future;
  then(resolve: (value: T) => TResult, reject: (value: any) => 
Future): Future;
  then(resolve: (value: T) => Future, reject: (value: any) => 
TResult): Future;
  then(resolve: (value: T) => TResult, reject: (value: any) => 
TResult): Future;

  catch(reject: (value: any) => Future): Future;
  catch(reject: (value: any) => TResult): Future;

  done(resolve: (value: T) => void, reject: (value: any) => void);
}
```

In the AsyncTable example you would write:

```ts
class AsyncTable {
  private m = new Map();

  set(keyP: Future, val: U): void {
keyP.done(key => { this.m.set(key, val); });
  }

  get(keyP: Future): Future {
return keyP.then(key => Future.accept(this.m.get(key))); // accept causes 
an unconditional lift.
  }
}
```

In Mark's second example, using the union type, you might instead have:

```ts
class AsyncTable {
  private m = new Map>();

  set(keyP: Future, val: Future): void;
  set(keyP: Future, val: U): void;
  set(keyP: Future, val: any): void {
keyP.done(key => { this.m.set(key, Future.resolve(val)); }); // autolift 
`Ref`-like union to `Future`
  }

  get(keyP: Future): Future {
return keyP.then(key => this.m.get(key)); // no need for unconditional 
lift, `then` will merge the already auto-lifted `Future`
 }
}
```

And Mark's third example might be:

```ts
class AsyncTable {
  private m = new Map>();

  // gah! TS needs union types...
  set(keyP: Future, val: Future): void;
  set(keyP: T, val: Future): void;
  set(keyP: Future, val: U): void;
  set(keyP: T, val: U): void;
  set(keyP: any, val: any): void {
Future.resolve(keyP).done(key => { this.m.set(key, Future.resolve(val)); 
});  // autolift key and val
  }

  get(keyP: Future): Future;
  get(keyP: T): Future;
  get(keyP: any): Future {
return Future.resolve(keyP).then(key => this.m.get(key)); // autolift key, 
val is already a `Future`
  }
}
```

Ron

From: es-discuss-boun...@mozilla.org [mailto:es-discuss-boun...@mozilla.org] On 
Behalf Of Claude Pache
Sent: Friday, May 10, 2013 11:25 AM
To: Mark S.Miller
Cc: public-script-co...@w3.org; es-discuss
Subject: Re: The Paradox of Partial Parametricity


Le 10 mai 2013 à 14:55, Mark S. Miller 
mailto:erig...@google.com>> a écrit :


[+es-discuss]

I didn't realize that I composed this in reply to a message only on 
public-script-coord. Further discussion should occur only on es-discuss. Sorry 
for the confusion.

On Fri, May 10, 2013 at 5:52 AM, Mark S. Miller 
mailto:erig...@google.com>> wrote:

I think the key exchange in these threads was

On Fri, May 3, 2013 at 4:17 PM, Jonas Sicking 
mailto:jo...@sicking.cc>> wrote:
[...]
I.e. permitting nested promises creates a more complex model and with
that you always get more confusion and more questions.

 On Sat, May 4, 2013 at 1:48 AM, Claus Reinke 
mailto:claus.rei...@talk21.com>> wrote:
[...]
>From the perspective of a-promise-is-just-like-other-wrapper-classes,
auto-flattening promises creates a more complex model


Together with each of their explanations about what they meant. They are both 
right. Lifting and auto-lifting do not mix. Q Promises give us autolifting with 
no lifting. Monadic promises would give us lifting but no autolifting. Having 
both in one system creates a mess which will lead programmers into the 
particular pattern of bugs Jonas warns about in his message.

For clarity I define the following APIs so I can define the three architectural 
choices in terms of the subset of these APIs they contain. Obviously, I do not 
intend to start a bikeshed yet on the particular names chosen for these 
operations. Let's stay focused on semantics, not terminology.

An upper case type variable, e.g. T, is fully parametric. It may be a promise 
or non-promise.
A lower case type variable, e.g. t, is constrained to be a non-promise. If you 
wish to think in conventional type terms, consider Any the top type immediately 
split into Pro

RE: Future cancellation

2013-05-01 Thread Ron Buckton
This is where something like an external cancellation source could be more 
effective:

```js
function getUser1(cancelToken) {
  return doXHR("/user.json", cancelToken);
}

function getUser2(cancelToken) {
  // immediate result, no need for cancellation
  return { "name": "domenic" };
}

function getUser3(cancelToken) {
  return doXHR("/user.json", cancelToken).then(function (user) {
user.metadata = " tags are old school";
  });
}

var cts = new CancellationTokenSource();
var usersF = Future.every(getUser1(cts.token), getUser2(cts.token), 
getUser3(cts.token));
usersF.done(function(users) {
});
cts.cancelAfter(5000); // timeout after 5 seconds.
```

Rather than subclassing Future, you use an external source provided by the 
caller to manage cancellation. Now it doesn't matter whether either of the 3 
methods have a return value that supports cancellation, and if the caller 
doesn't need to cancel, it can provide null or undefined.

Ron

> -Original Message-
> From: es-discuss-boun...@mozilla.org [mailto:es-discuss-
> boun...@mozilla.org] On Behalf Of Domenic Denicola
> Sent: Wednesday, May 1, 2013 11:23 AM
> To: Tab Atkins Jr.; Bill Frantz
> Cc: public-script-co...@w3.org; Brendan Eich; es-discuss
> Subject: RE: Future cancellation
> 
> From: Tab Atkins Jr. [jackalm...@gmail.com]
> 
> > I think you're making this far too complicated.  It's much simpler than 
> > this:
> 
> I disagree. An abstraction boundary gets broken. Consider:
> 
> ```js
> function getUser1() {
>   return doXHR("/user.json");
> }
> 
> function getUser2() {
>   return { "name": "domenic" };
> }
> 
> function getUser3() {
>   return doXHR("/user.json").then(function (user) {
> user.metadata = " tags are old school";
>   });
> }
> ```
> 
> Here, `getUser1()` returns a cancellable promise, but `getUser2()` does not,
> even though they should have the same semantics. Worse, `getUser3()` isn't
> cancellable, even though it was originally derived from an XHR. Trying to fix
> the `getUser3()` case is what takes you down the slope of complex additional
> semantics.
> 
> Much better would be if a hypothetical future XHR utility returned a `{
> promise, abort }` object, with no logical connection between the `abort` and
> the `promise` (besides maybe rejecting the promise with a well-known
> error). This seems much better than trying to make a general cancellation
> concept for promises and overloading them with additional semantics about
> the operation being performed.
> ___
> 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: Future cancellation

2013-04-30 Thread Ron Buckton
> -Original Message-
> From: Domenic Denicola [mailto:dome...@domenicdenicola.com]
> Sent: Tuesday, April 30, 2013 9:25 PM
> To: Jonas Sicking; Ron Buckton
> Cc: public-script-co...@w3.org; es-discuss
> Subject: RE: Future cancellation
> 
> From: es-discuss-boun...@mozilla.org [mailto:es-discuss-
> boun...@mozilla.org] On Behalf Of Jonas Sicking
> 
> > It isn't actually surprising that the same issues arise. ProgressFuture
> basically delivers progress about an "operation" rather than a "result".
> 
> I agree. I think both progress and cancellation (of underlying operations) are
> attractive nuisances. They seem like they fit in well with the model, and
> would be useful for certain use cases. But they are actually very different,
> and not tied to the underling promise semantics at all—which are of a first
> class value representing a promised "result," as you put it, not representing
> an ongoing "operation."
> 
> I lean toward not specifying or including them at all. Although you can try to
> stuff them naively into the promise semantics, you end up needing to
> complicate the conceptual model in order to make them behave as you wish.
> As you point out, this is clearly visible with the various combinators. But 
> it's
> also visible in basic semantic questions that arise: e.g. downward progress
> propagation/transformation, or the role of throwing inside a progress
> handler, or upward cancellation progagation/reaction, or downward
> cancellation forking, or the role of rejections in cancellation. You soon 
> realize
> that you're trying to smush in semantics where they don't belong.
> 
> In other words, separate abstractions for cancellation or progress, unrelated
> to promises, seem best.

This is roughly the case with .NET/C# cancellation. In .NET you use an external 
object to represent cancellation. If a function returns a Future (or "Task" in 
.NET), it's the function author's decision as to whether they want to accept a 
cancellation token. This allows the author control over whether they want to 
support cancellation. It's up to the caller to choose to construct a 
cancellation token and feed it to the function call. This allows for separation 
of responsibilities between the Future (which is only responsible for 
delivering asynchronous completion) and Cancellation (which can provide control 
over the operation). In .NET though, Tasks do participate in cancellation. They 
have a unique internal state that represents a cancelled task and a level of 
control over how to handle chained continuations (via the 
TaskContinuationOptions enum).

The same can be said for progress notifications in .NET Tasks, as they require 
a synchronization context to post progress notifications back to the caller who 
may be in a different thread.  This does illustrate your point though, 
regarding how Futures, cancellation, and progress are related but distinct.

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


RE: Future cancellation

2013-04-30 Thread Ron Buckton
Jonas, 

As I mentioned to Alex Russel, I'm also interested in the benefits of using a 
subclass. I have two additional gists around cancellation, one that uses an 
external token for cancelation [1] (similar to .NET/C#), and another that uses 
a subclass [2] (though I still need to spend some additional time on the 
subclass sample).

[1] https://gist.github.com/rbuckton/5490373
[2] https://gist.github.com/rbuckton/5490482

I agree with the sentiment that Future#cancel is a bad idea. 

Ron

> -Original Message-
> From: Jonas Sicking [mailto:jo...@sicking.cc]
> Sent: Tuesday, April 30, 2013 4:47 PM
> To: Ron Buckton
> Cc: es-discuss; public-script-co...@w3.org; Tab Atkins Jr.
> Subject: Re: Future cancellation
> 
> On Mon, Apr 29, 2013 at 6:57 PM, Ron Buckton 
> wrote:
> > I've created separate gists for three different ways that I am
> > currently investigating as a means to support the cancellation of a
> > Future. These can be found here:
> >
> >
> >
> > 1.   Cancellation using Future: https://gist.github.com/rbuckton/5486149
> >
> > 2.   Cancellation using Future.cancelable:
> > https://gist.github.com/rbuckton/5484591
> >
> > 3.   Cancellation using Future#cancel:
> > https://gist.github.com/rbuckton/5484478
> >
> >
> >
> > Each has a list of some of the benefits and issues I've seen while
> > experimenting with each approach, as well as possible changes to the
> > various APIs or algorithms for Future to make each happen.
> >
> >
> >
> > In general, cancellation of a Future can be beneficial in a number of cases.
> > One example is the case where you are requesting a resource from a
> > remote server using XHR. If the request was being made to fetch a page
> > of data, and the user opted to move to the next page before the
> > current page completed loading, it no longer becomes necessary to
> > continue fetching the remote resource. In addition, it is no longer
> > necessary to handle any additional computation or transformation logic
> > that would have resulted from the successful completion of the fetch
> > operation. Having the ability to cancel the request allows an
> > application to quickly release resources that it no longer needs.
> >
> >
> >
> > It is also useful to be able to handle the cancelation of a long
> > running task that might be executing in a Worker. In this case,
> > cleanup logic that is part of cancelation would request the worker to
> > close, ending the current operation and releasing resources.
> >
> >
> >
> > Both of the above examples are indicative of cancelling the root of an
> > operation, but there are also circumstances where you might want to
> > cancel a chained Future and any Future chained from it, without canceling
> the root.
> > In the previous example regarding paged data, I might wish to allow
> > the fetch operation to complete so that I could cache the data for
> > quick retrieval, but would only want to cancel any possible UI updates
> > that might occur in a chained Future.
> >
> >
> >
> > I'm interested to hear what others think with respect to properly
> > handling cancellation with Futures.
> 
> I do not think that we should add cancellation on the base Future interface. 
> I.e.
> we shouldn't make *all* Futures cancellable.
> 
> Cancelability should only be possible when the implementation of the Future
> would actually stop doing work if the Future is cancelled. I.e.
> cancelling a Future shouldn't simply prevent the result callbacks from being
> called, but it should prevent whatever work is needed to calculate the result
> from happening.
> 
> However it would be very complex and expensive if we had to make all APIs
> that want to use Futures also support being cancelled.
> 
> The solution is to create a subclass of Future which allows the back-end work 
> to
> be cancelled. I.e. a CancelableFuture, or AbortableFuture. This subclass would
> have a .cancel() or .abort() method on it. The FutureResolver created when the
> CancelableFuture is created would have a callback which is called when
> .cancel()/.abort() is called.
> 
> This would be useful if we create an Future-based API for doing network
> requests or file reading.
> 
> In other words, the should be the choice of the implementor of a given API to
> determine if it wants to return a Future which can be cancelled, or one that
> can't. Obviously this needs to be documented for that API, just like you
> document that the API returns a Future at all.
> 
> / Jonas


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


Re: Future cancellation

2013-04-30 Thread Ron Buckton
Alex,

Thank you for the feedback.  I’ve also added two more gists:

4. Cancellation using CancellationTokenSource: 
https://gist.github.com/rbuckton/5490373
5. Cancellation using CancelableFuture subclass: 
https://gist.github.com/rbuckton/5490482

Each one of these is an attempt to find out exactly what does and doesn’t work 
with various mechanisms for cancellation that have been discussed on these 
lists as well as in various libraries.

In [1] I added the synchronous flag as a way to ensure that the Future that is 
used for cancellation can resolve and have its resolve callbacks run in time. 
It’s not exactly necessary but there are some cases where not being able to 
cancel synchronously could bite a developer:

function someAsync(cancelFuture) {
  return new Future(function (resolver) {
var handle = setImmediate(function () { … });
cancelFuture.done(function () { clearImmediate(handle); });
  });
}

var { token, cancel } = createCanceler();
var f = someAsync(token);
cancel();

Due to asynchronous resolution, even though cancel() is called synchronously it 
will be scheduled *after* the setImmediate call.

[2] was based on a side discussion around cancellation and similarities to 
revocable Proxies.

[3] was based on providing a simple means of cancellation, but I agree that 
there is a danger that a Future that is referenced by multiple consumers could 
be canceled by any consumer.

[4] is inspired by cooperative cancellation of Tasks in .NET. I’ve used this 
quite often and found it to be a powerful cancellation mechanism. It has the 
advantage of being very explicit about where responsibilities lie as part of 
cancellation and reducing pollution of the Future API, but it does add 
additional complexity around setup. I’m personally in favor of this approach, 
though not so fond of the name of types.  [1] is partially based on this 
approach as well, except that CTS cancels synchronously and can automatically 
reject a Future.

[5] is a possible approach (albeit a naïve implementation) of cancellation via 
a subclass. In its current incarnation it suffers from the same issues a [1] 
and [2], but can be mitigated by having it directly call the resolver’s resolve 
algorithm with the synchronous flag set. It also gets lost when using 
Future.any, etc.

My intent currently is not to advocate any of these approaches. Rather; I’m 
trying to catalogue each approach as I’ve come across them specifically to 
gather this kind of feedback.

Best regards,
Ron

Sent from Windows Mail

From: Alex Russell
Sent: ‎Tuesday‎, ‎April‎ ‎30‎, ‎2013 ‎2‎:‎54‎ ‎AM
To: Ron Buckton
Cc: es-discuss, public-script-co...@w3.org, Tab Atkins Jr.

These are horribly confused -- and likely foot-gun -- designs.

First, synchronous resolution needs some justification. I don't understand why 
you've added it in the first design. The question of "does the Resolver know it 
is resolved?" is entirely independent of the visibility of that resolution to 
the outside world. I don't think this flag even makes sense.

In terms of blessing one or another static method for generating the 
cancellable tuple (as you do in your first two designs), why does it have to be 
in the design at this point? The current design in DOM provides a small 
contract to keep us from fighting over how to distinguish cancellation from 
other error values (the side-contract everyone would need to re-create at great 
expense), but purposefully avoids doing this for the sake of simplicitly. I 
don't get why you're trying to expand this contract in the core spec. Just 
subclass. Should it become so common, we can revisit this later.

Lastly, your final design is irretrievably broken in a way the first two 
aren't: it vends to anyone who has a handle to the Future the capability to 
reject it.

The DOM design has studiously avoided this class of fatal design errors so far. 
It's the key reason why Resolvers and Futures are separate objects. No such 
design will fly in this group.

Regards

On Tuesday, April 30, 2013, Ron Buckton wrote:
I’ve created separate gists for three different ways that I am currently 
investigating as a means to support the cancellation of a Future. These can be 
found here:


1.   Cancellation using Future: https://gist.github.com/rbuckton/5486149

2.   Cancellation using Future.cancelable: 
https://gist.github.com/rbuckton/5484591

3.   Cancellation using Future#cancel: 
https://gist.github.com/rbuckton/5484478

Each has a list of some of the benefits and issues I’ve seen while 
experimenting with each approach, as well as possible changes to the various 
APIs or algorithms for Future to make each happen.

In general, cancellation of a Future can be beneficial in a number of cases.  
One example is the case where you are requesting a resource from a remote 
server using XHR. If the request was being made to fetch a page of data, and 
the user opted to move to the next page befo

Future cancellation

2013-04-29 Thread Ron Buckton
I've created separate gists for three different ways that I am currently 
investigating as a means to support the cancellation of a Future. These can be 
found here:


1.   Cancellation using Future: https://gist.github.com/rbuckton/5486149

2.   Cancellation using Future.cancelable: 
https://gist.github.com/rbuckton/5484591

3.   Cancellation using Future#cancel: 
https://gist.github.com/rbuckton/5484478

Each has a list of some of the benefits and issues I've seen while 
experimenting with each approach, as well as possible changes to the various 
APIs or algorithms for Future to make each happen.

In general, cancellation of a Future can be beneficial in a number of cases.  
One example is the case where you are requesting a resource from a remote 
server using XHR. If the request was being made to fetch a page of data, and 
the user opted to move to the next page before the current page completed 
loading, it no longer becomes necessary to continue fetching the remote 
resource. In addition, it is no longer necessary to handle any additional 
computation or transformation logic that would have resulted from the 
successful completion of the fetch operation. Having the ability to cancel the 
request allows an application to quickly release resources that it no longer 
needs.

It is also useful to be able to handle the cancelation of a long running task 
that might be executing in a Worker. In this case, cleanup logic that is part 
of cancelation would request the worker to close, ending the current operation 
and releasing resources.

Both of the above examples are indicative of cancelling the root of an 
operation, but there are also circumstances where you might want to cancel a 
chained Future and any Future chained from it, without canceling the root. In 
the previous example regarding paged data, I might wish to allow the fetch 
operation to complete so that I could cache the data for quick retrieval, but 
would only want to cancel any possible UI updates that might occur in a chained 
Future.

I'm interested to hear what others think with respect to properly handling 
cancellation with Futures.

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


RE: A Challenge Problem for Promise Designers

2013-04-29 Thread Ron Buckton
> -Original Message-
> From: Tab Atkins Jr. [mailto:jackalm...@gmail.com]
> Sent: Monday, April 29, 2013 1:20 PM
> To: Ron Buckton
> Cc: Mark Miller; David Sheets; Mark S. Miller; es-discuss; public-script-
> co...@w3.org; David Bruant; Dean Tribble
> Subject: Re: A Challenge Problem for Promise Designers
> 


> > * Added Future.from to perform explicit assimilation (with only one
> > level of unwrap, as with Future#then)
> 
> Like I said, Domenic says that recursive assimilation is useful, and I'm 
> inclined
> to believe him, as he has a lot more experience in getting arbitrary thenables
> to play nicely together than I do. ^_^

I'll tinker with it and run some tests. 
 
> > * Added Future.isFuture to test for native Futures
> 
> For the purpose of library code, you don't need this - just use "x instanceof
> Future".  Future.isFuture is only useful for the language to define, so that 
> it
> can tell something is a Future cross-frame.

The intent is to eventually have a rough polyfill for ES5 and earlier, so if 
Future.isFuture becomes part of the spec this would likely match using some 
kind of pseudo-symbol polyfill. 

> 
> ~TJ

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


RE: A Challenge Problem for Promise Designers

2013-04-29 Thread Ron Buckton
> -Original Message-
> From: Tab Atkins Jr. [mailto:jackalm...@gmail.com]
> Sent: Monday, April 29, 2013 11:21 AM
> To: Ron Buckton
> Cc: Mark Miller; David Sheets; Mark S. Miller; es-discuss; public-script-
> co...@w3.org; David Bruant; Dean Tribble
> Subject: Re: A Challenge Problem for Promise Designers
> 
> On Mon, Apr 29, 2013 at 11:03 AM, Ron Buckton 
> wrote:
> > Thanks for the clarifications re: Future as a monad. My understanding of
> this is as follows (please correct me if I am wrong):
> >
> > * The expected result of the resolve/reject callbacks passed to
> Future#then is itself a Future.
> > * If the result of the resolve/reject callbacks is not a Future it is 
> > logically
> lifted into a Future, by accepting the value on the Future that is the result 
> of
> Future#then.
> > * The Future result of the callback is merged into the Future returned
> Future#then then by chaining to either Future#then (Future#done?) of the
> callback result.
> > * Given this, it is not usually necessary to "recursively unwrap" or 
> > "flatten"
> a Future. As a result Future#then should not flatten the result. This would
> preserve Future.accept(Future.accept(value)).then().then(F => /* F is
> Future(value) */).
> 
> All correct.  (Some of your precise mechanical details are probably wrong, but
> you got all the important bits.)

I updated [1] my rough implementation of Future based on this discussion. This 
has the following changes from the previous [2] version which was based on the 
DOM spec for Future:

* The resolver's resolve algorithm tests value to determine if it is a Future 
instance (rather than a "thenable"). This could later be done by checking 
branding or by checking for a symbol.
* The resolver's resolve algorithm only unwraps the value once if it is a 
Future, rather than performing flattening. It does this by calling the 
resolver's accept algorithm in the "resolve" future callback for rather than 
the resolve algorithm.
* In the steps for Future#then, if the "resolveCallback" is null, the "resolve" 
callback becomes a future callback for resolver and its accept algorithm. This 
is to preserve the value for something like: 

Future.accept(Future.accept(value)).then().then(F => /* F is Future(value) 
*/)
Future.accept(Future.accept(Future.accept(value))).then().then(FF => /* FF 
is Future(Future(value)) */)

* In the steps for some/any/every, the future callbacks that are created that 
used the resolver's resolve algorithm now use the resolver's accept algorithm. 
This is to preserve the value for something like:

Future.any(Future.accept(Future.accept(value))).then(F => /* F is 
Future(value) */)
Future.any(Future.accept(Future.accept(Future.accept(value.then(FF => 
/* FF is Future(Future(value)) */)

* Added Future.from to perform explicit assimilation (with only one level of 
unwrap, as with Future#then)
* Added Future.isFuture to test for native Futures

Hopefully I've captured the mechanical details correctly in the implementation.

[1, updated implementation] 
https://github.com/rbuckton/promisejs/blob/master/Future1/Future.ts
[2, spec implementation] 
https://github.com/rbuckton/promisejs/blob/master/Future0/Future.ts

Ron

> 
> > I can also agree that it is inherently unsafe to assimilate "thenables" for
> Future.resolve/FutureResolver#resolve, due to possible collisions with the
> property name on existing objects such as with casper.js. This kind of 
> collision
> is the same rationale for having an @iterator symbol for iterators, though I
> wouldn't think the same resolution is likely the best result in this case. I 
> am of
> the opinion that native Futures should only resolve native Futures (or
> possibly their subclasses). To assimilate you could have a Future.of (or
> possibly Future.from to match Array.from for "array-like" objects), which
> would assimilate "future-like" objects (i.e. "thenables"), but only via one
> level of unwrapping and not recursively.
> 
> I'm fine with the concept of using branding (via a symbol) to denote that
> something should be treated like a future.  I'm also fine with only allowing
> Promises and subclasses.  Whatever people decide is better.
> 
> Domenic, after a lot of experience, thinks that the assimilation procedure
> should be recursive (presumably "bottoming out" when it hits a native
> promise).  I'm fine with that.  It does mean that if you need to assimilate a
> thenable for a Casper object, it'll do the wrong thing, but that's the price 
> you
> pay for arbitrary library compat.  If you know your foreign thenable is only a
> s

RE: yield* desugaring

2013-04-29 Thread Ron Buckton
> -Original Message-
> From: Andy Wingo [mailto:wi...@igalia.com]
> Sent: Monday, April 29, 2013 11:56 AM
> To: Ron Buckton
> Cc: Brendan Eich; es-discuss
> Subject: Re: yield* desugaring
> 
> On Mon 29 Apr 2013 19:25, Ron Buckton  writes:
> 
> > The desugaring for yield* in the face of using { value?, done? } is more 
> > likely
> (without refutable matching or let expressions for the moment):
> >
> > ```js
> > let a;
> > {
> > [...]
> > a = result;
> > }
> > ```
> 
> Correct me if I am wrong, but I don't think this works, given that like 
> "yield X",
> "yield* X" is an expression.

That's correct, it's not quite right given the fact it needs to be an 
expression. I've been more focused on how to rewrite this via transpiler in ES5.

> 
> close() does not seem to have much value given that it isn't part of the
> iterators specification, and one can do any needed action by doing a
> throw() on the iterator and relying on the generator to have a finally block 
> if
> needed.
> 
> Andy


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


RE: A Challenge Problem for Promise Designers

2013-04-29 Thread Ron Buckton
Thanks for the clarifications re: Future as a monad. My understanding of this 
is as follows (please correct me if I am wrong):

* The expected result of the resolve/reject callbacks passed to Future#then is 
itself a Future.
* If the result of the resolve/reject callbacks is not a Future it is logically 
lifted into a Future, by accepting the value on the Future that is the result 
of Future#then.
* The Future result of the callback is merged into the Future returned 
Future#then then by chaining to either Future#then (Future#done?) of the 
callback result. 
* Given this, it is not usually necessary to "recursively unwrap" or "flatten" 
a Future. As a result Future#then should not flatten the result. This would 
preserve Future.accept(Future.accept(value)).then().then(F => /* F is 
Future(value) */).

I can also agree that it is inherently unsafe to assimilate "thenables" for 
Future.resolve/FutureResolver#resolve, due to possible collisions with the 
property name on existing objects such as with casper.js. This kind of 
collision is the same rationale for having an @iterator symbol for iterators, 
though I wouldn't think the same resolution is likely the best result in this 
case. I am of the opinion that native Futures should only resolve native 
Futures (or possibly their subclasses). To assimilate you could have a 
Future.of (or possibly Future.from to match Array.from for "array-like" 
objects), which would assimilate "future-like" objects (i.e. "thenables"), but 
only via one level of unwrapping and not recursively.

I'm still concerned about cancellation, but will spin up another thread to 
hopefully spark some thoughtful discussion on the topic.

Ron

> -Original Message-
> From: Tab Atkins Jr. [mailto:jackalm...@gmail.com]
> Sent: Saturday, April 27, 2013 8:32 PM
> To: Mark Miller
> Cc: David Sheets; Mark S. Miller; es-discuss; public-script-co...@w3.org; Ron
> Buckton; David Bruant; Dean Tribble
> Subject: Re: A Challenge Problem for Promise Designers
> 
> On Sat, Apr 27, 2013 at 5:46 PM, Mark Miller  wrote:
> > I am worried that we're again separated by a common terminology more
> > than we are by an actual technical disagreement. I am arguing against
> > an unconditional lift operation that would make a promise-for-promise.
> > Or at least seeking to provoke someone to provide a compelling example
> > showing why this is useful[1]. What all the recent messages seem to be
> > arguing for is the existence of a non-assimilating and perhaps a
> > non-unwrapping lift-ish operation, so that one can make a
> > promise-for-thenable. I have no objection to being able to make a
> promise-for-thenable.
> 
> The reasoning *for* an unconditional lift operator is that promises, as
> specified by DOM Futures or Promises/A+, are roughly a monad, and having
> an unconditional lift is required to satisfy the monad laws.
> Being a monad is useful, in ways similar to how being an iterable is useful, 
> or
> an array-like, or many other typeclasses that various languages recognize.
> 
> For example, Future.all() is almost equivalent to a variadic liftA() (name 
> taken
> from Haskell), which takes a function and any number of arguments, all
> wrapped in some particular monad, and executes the function with its
> arguments in the way that the monad prefers.  For promises, that means "if
> every promise accepts, execute the function and return an accepted promise
> for the return value; otherwise, return a rejected promise".  This sort of
> function comes *for free* once a class has been established as a monad, just
> as Python's very useful itertools library applies "for free" to anything that
> establishes itself as an iterable.  You don't have to write any special code 
> to
> make it happen; just the fact that promises are monads means that the
> generically-written liftA() method automatically works.
> 
> > The clearest sign to me of the potential for misunderstanding is the
> > use of the term "flattening" for unwrapping of thenables. To be clear,
> "flattening"
> > is about promises -- it is just the conditional autolifting seen from
> > the other side (as I now understand the term autolifting -- thanks).
> > "unwrapping" is what happens to thenables. "Assimilation" is recursive
> > unwrapping of thenables. I understand that it can be difficult to keep
> > these distinctions straight. I wouldn't be surprised if I've been
> > sloppy myself with these terms earlier in these threads. But now that
> > we're zeroing in, these fine distinctions matter.
> 
> I'm not sure where you got this precise terminology, but I'm willing to 

RE: yield* desugaring

2013-04-29 Thread Ron Buckton
Was there consensus on the return value of the various generator methods being 
{ value?, done? } for next/send/throw? Is it needed for close? 

The desugaring for yield* in the face of using { value?, done? } is more likely 
(without refutable matching or let expressions for the moment):


```js
let a = yield* EXPR;
```

```js
let a;
{
let g = EXPR;
let received = void 0, send = true, result = void 0;
try {
while (true) {
let { value, done } = send ? g.send(received) : g.throw(received);
if (done) {
result = value;
break;
}
try {
received = yield value;
send = true;
}
catch (e) {
received = e;
send = false;
}
}
} 
finally {
try { g.close(); } catch (ignored) { }
}
a = result;
}
```

Ron

> -Original Message-
> From: es-discuss-boun...@mozilla.org [mailto:es-discuss-
> boun...@mozilla.org] On Behalf Of Brendan Eich
> Sent: Monday, April 29, 2013 9:48 AM
> To: Andy Wingo
> Cc: es-discuss
> Subject: Re: yield* desugaring
> 
> Just a straw-spec device, not proposed for ES6 or 7.
> 
> /be
> 
> Andy Wingo wrote:
> > Hi again,
> >
> > On Mon 29 Apr 2013 17:37, Andy Wingo  writes:
> >
> >>let (g = EXPR) {
> >>  let received = void 0, send = true;
> >>  while (true) {
> >>let next = send ? g.send(received) : g.throw(received);
> >>if (next.done)
> >>  break;
> >>try {
> >>  received = yield next.value;  // ***
> >>  send = true;
> >>} catch (e) {
> >>  received = e;
> >>  send = false;
> >>}
> >>  }
> >>  next.value;
> >>}
> >
> > Beyond the scoping error of "next", this desugaring uses let
> > expressions, which AFAICS are not in the spec and have not been
> > discussed in a few years.  Are they actually still a thing?
> >
> > Andy
> > ___
> > 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: A Challenge Problem for Promise Designers

2013-04-27 Thread Ron Buckton
Here is a case where flattening helps:

function executeAndWaitForComplete(command) {
  return getJSON(commandUrl + command)
.then(function (commandResult) {
  if (commandResult.complete) {
return commandResult.model;
  }
  var statusUrl = commmandResult.statusUrl;
  return pollForCommandComplete(statusUrl);
})
}

function pollForCommandComplete(statusUrl) {
  return new Future(function(resolver) {
var poll = function (pollResult) {
  if (pollResult.done) {
resolve.resolve(pollResult.model);
  }
  else {
setTimeout(function() {
  getJSON(statusUrl).done(poll, resolver.reject);
}, 500);
  }
}
getJSON(statusUrl).done(poll, resolver.reject);
  });
}

In this example, the server will receive a command from the client and will 
process it asynchronously. The client then needs to poll an endpoint to check 
for completion of the command. Just using Futures, flattening is helpful here. 
Without flattening, executeAndWaitForComplete would could return either a 
Future OR return a Future>.  In a non flattening world, 
the developer would have to change the function to:

function executeAndWaitForComplete(command) {
  return new Future(function(resolver) {
getJSON(commandUrl + command)
  .done(function (commandResult) {
if (commandResult.complete) {
  resolver.resolve(commandResult.model);
}
var statusUrl = commmandResult.statusUrl;
pollForCommandComplete(statusUrl).done(resolver.resolve, 
resolver.reject);
  }, resolver.reject)
});
}

With flattening, the first version is less code for the developer. With 
flattening its possible to run into odd errors without some kind of static 
analysis since JS is not type safe.

Ron

Sent from Windows Mail

From: Tab Atkins Jr.
Sent: ‎Friday‎, ‎April‎ ‎26‎, ‎2013 ‎2‎:‎24‎ ‎PM
To: David Bruant
Cc: Mark S. Miller, public-script-co...@w3.org, Mark Miller, Dean Tribble, 
es-discuss

On Fri, Apr 26, 2013 at 1:39 PM, Tab Atkins Jr.  wrote:
> On Fri, Apr 26, 2013 at 6:36 AM, David Bruant  wrote:
>> Le 26/04/2013 14:54, Kevin Smith a écrit :
>>>
>>> What exactly is the controversy here?
>>>
>>> I think we all agree with the semantics of "then" as specified in
>>> Promises/A+.  (If not, then we have a really big problem!)
>>>
>>> If so, then the only real controversy is whether or not the API allows one
>>> to create a promise whose eventual value is itself a promise.  Q does not:
>>> it provides only "resolve" and "reject".  DOM Futures do by way of
>>> "Future.accept".  As far as I know, there's nothing about Q's implementation
>>> that would make such a function impossible, it just does not provide one.
>>
>> I believe at this point the question isn't so much "can I build a promise
>> for a promise?", but rather "what should be the default Future semantics?"
>> Namely:
>>
>> Future.accept(5)
>> .then(function(x){
>> return Future.accept(x);
>> })
>> .then(function(y){
>> // is y a Future?
>> })
>>
>> I'm arguing in favor of y being guaranteed to be a non-Future value. It is
>> my understanding others would want y to be a Future.
>> That would be the controversy as I understand it.
>
> No.  Future callbacks can return Futures, which then chain (the return
> value of then adopts the state of the callback's return value).  This
> is the big "monad" benefit that we keep talking about.

To lay it out even more clearly for any bystanders, in the following code:

getAFuture()
  .then(function(x) {
return doSomeWork(x);
  })
  .then(function(y) {
// is y a Future?
  });

The answer to the question is "no", *regardless of whether doSomeWork
returns a plain value or a Future for a plain value*.

If doSomeWork() returns a plain value, the future returned by the
first .then() call accepts with that value.  If doSomeWork() returns a
future that eventually accepts, the future returned by the first
.then() call waits until it accepts, and then also accepts with the
same value.

This all happens without recursive unwrapping.  It's just a feature of
how this kind of thing works (it's a result of Futures matching the
"monad" abstraction).

The only way that y will become a Future is if doSomeWork() explicitly
and purposefully returns a future for a future for a value (in other
words, Future>).  In this case, the future returned by the
first .then() call waits until the outer Future from the return value
finishes, then accepts with its value, and "this value" happens to be
a Future.

This sort of thing does not happen accidentally.  It's hard to make
nested futures unless you're doing it on purpose, or you have no idea
what you're doing.  In the first case, we want to trust the author,
and in the second case, it's probably better for everyone involved if
the code fails in a fairly obvious way, rather than attempting to
paper over the problem.  If you're competent and just doing the
natural 

RE: Futures

2013-04-26 Thread Ron Buckton
I have an implementation in Typescript/ES5 at 
https://github.com/rbuckton/promisejs/tree/master/Variations with a test suite 
that can be run from node.

Ron

Sent from my Windows Phone

From: Kevin Smith
Sent: ‎4/‎26/‎2013 11:47 AM
To: Juan Ignacio Dopazo
Cc: Brendan Eich; Mark S. 
Miller; Douglas 
Crockford; 
public-script-co...@w3.org; Norbert 
Lindenberg; Markus 
Lanthaler; 
EcmaScript
Subject: Re: Futures


If resolved called the thenable's then() with accept and reject, it would only 
unwrap one layer.


Good spec googles (I think).  I just whiteboarded it and came to the same 
conclusion.  Does anyone else have a prototype implementation they can run this 
program on?

{ Kevin }

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


Re: A Challenge Problem for Promise Designers (was: Re: Futures)

2013-04-25 Thread Ron Buckton
I’m not sure I fully grok the use cases for FutureResolver#accept and having  
Future>. Having to call an Unwrap extension method on a 
Task> in .NET is an unfortunate necessity. Also, since Future#then 
implicitly resolves a future it is difficult to return a Future> 
from a then.

In every case where I've used something like a Future it has always seemed more 
convenient to have it implicitly unwrap.

For native Futures, I don’t think it makes sense to try and unwrap just any 
object with a callable “then”. Its a necessity today for Promise libraries in 
ES5 as there’s no ideal way to brand an object as a Future.

This is what seems to make sense to me from a practical standpoint when using 
native Futures:


  *   If you resolve a Future (A) with a Future (B), the result of Future (A) 
should be B.
  *   This implicit unwrap should only work out of the box for Future 
subclasses or branded Futures.
  *   To coerce a “thenable” should be an explicit opt-in (e.g. Q(), or 
Future.of).
  *   There should be a well-defined mechanism for chaining futures from 
subclasses to preserve capabilities (ProgressFuture, etc.). One option might be 
a FutureFactory, another is to have subclasses override the .then method.
  *   An alternative to FutureResolver#accept that would allow for an explicit 
Future for a Future, might be to box the future, either explicitly (e.g. 
resolver.resolve({ future: f })) or with something like a Future.box() that 
encapsulates the future. In this way, if you need a future for a future you can 
support it on both FutureResolver and “then”.


A Future for a Future seems like a corner case compared to the broader 
simplicity of an implicit unwrap.

If we had Future.box() instead of FutureResolver#accept, we might be able to do 
things like:

function someFutureFutureV() {
  return new Future(function (resolver) {
var F = someFutureV();
var Fboxed = Future.box(F); // some special instance with a .value property?
// F === Fboxed.value;
resolver.resolve(Fboxed); // i.e. resolver.resolve(Future.box(F)) instead 
of resolver.accept(F)
  })
}

someFutureFutureV().then(function (F) {
  // “then” unboxes Fboxed, just as it might have unwrapped F were it not boxed.
  // ...
  return Future.box(F); // another Fboxed
}).then(function (F) {
  // F is again preserved, this time from a call to then
  // ...
  return F; // no boxing this time
}).then(function (V) {
  // F is now unwrapped to V
});

While slightly more complicated for the FutureFuture case, the expectations are 
simpler for the broader usage scenarios, and the API surface is simpler (no 
FutureResolver#accept) for the most common use cases. If you really do intend 
to have a FutureFuture, Future.box would let you have a single way to opt in 
for both FutureResolver#resolve as well as Future#then.

Ron


Sent from Windows Mail

From: Tab Atkins Jr.
Sent: ‎Thursday‎, ‎April‎ ‎25‎, ‎2013 ‎8‎:‎38‎ ‎PM
To: Mark S. Miller
Cc: Mark Miller, es-discuss

On Thu, Apr 25, 2013 at 6:49 PM, Mark S. Miller  wrote:
> What is the semantics of Future.resolve?

Creates an already-accepted future using the "resolve" algorithm,
which is the same magic that happens to the return value of a .then()
callback (if it's a future, it adopts the state; otherwise, it accepts
with the value).

In other words, "If this is a future, use it; otherwise, make me a
future for it".

~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: Futures (was: Request for JSON-LD API review)

2013-04-24 Thread Ron Buckton
Be it Promise or Future, instanceof won't work across frames. It would likely 
still require a Future.isFuture/Promise.isPromise just as we need to have 
Array.isArray now. That is, of course, unless we can use symbols for branding 
in a fashion that library authors could use without forking their library for 
pre- and post- ES6 (or later) versions.

From: es-discuss-boun...@mozilla.org [mailto:es-discuss-boun...@mozilla.org] On 
Behalf Of Dean Landolt
Sent: Wednesday, April 24, 2013 12:09 PM
To: Tab Atkins Jr.
Cc: Mark S. Miller; es-discuss
Subject: Re: Futures (was: Request for JSON-LD API review)



On Wed, Apr 24, 2013 at 2:18 PM, Tab Atkins Jr. 
mailto:jackalm...@gmail.com>> wrote:
On Wed, Apr 24, 2013 at 10:51 AM, Domenic Denicola
mailto:dome...@domenicdenicola.com>> wrote:
> From: Andreas Rossberg [rossb...@google.com]
>> Mark, could you summarize the rationale for this, or provide a more specific 
>> link to the appropriate bit of the discussion you are referring to?
>
> I'm not Mark, and he might have something more specific in mind, but this 
> summary was pretty helpful:
>
> https://gist.github.com/ForbesLindesay/5392612
These aren't very good reasons, unfortunately.  :/

The JQP... problem can be solved by a single "flatten" operation added
to the API.  This is a totally reasonable operation, same as it would
be for Arrays.


I'll do you one better and suggest the JQP... problem can go away completely 
the day TC39 decides on a built-in -- let's call it `Promise` for the sake of 
argument. A new spec, call it Promises/A++, could then be defined which states 
that this class is to be included in the proto chain of compatible promises. 
For the sake of interoperable shimming libraries should create this global if 
it doesn't exist (this part's a little sketchy but I can't think of a good 
alternative that doesn't involve abusing __proto__).

Now, instead of a ducktest for a `then` method the promise check would instead 
be specified as `instanceof Promise`. For the sake of backward compatibility 
libraries can choose to add a Promise.prototype.then so that these new promises 
work with old promise libs too. If it comes comes to it, old promises can be 
made to work in the new regime with a little __proto__ hacking.

The only reason thenables won is because library authors didn't have a formal 
namespace to hang these things. This is what ultimately made assimilation 
necessary, and it's a non-issue as soon as TC39 specifies a Promise base class.
[snipped the rest, but FWIW I totally agree w/ Tab]
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Futures (was: Request for JSON-LD API review)

2013-04-24 Thread Ron Buckton
Resending due to a mail error.

> -Original Message-
> From: es-discuss-boun...@mozilla.org [mailto:es-discuss-
> boun...@mozilla.org] On Behalf Of Tab Atkins Jr.
> Sent: Wednesday, April 24, 2013 11:18 AM
> To: Domenic Denicola
> Cc: Mark S. Miller; es-discuss
> Subject: Re: Futures (was: Request for JSON-LD API review)
>
> On Wed, Apr 24, 2013 at 10:51 AM, Domenic Denicola
>  wrote:
> > From: Andreas Rossberg [rossb...@google.com]
> >> Mark, could you summarize the rationale for this, or provide a more
> specific link to the appropriate bit of the discussion you are referring to?
> >
> > I'm not Mark, and he might have something more specific in mind, but
> > this
> summary was pretty helpful:
> >
> > https://gist.github.com/ForbesLindesay/5392612
>
> These aren't very good reasons, unfortunately.  :/
>
> The JQP... problem can be solved by a single "flatten" operation added
> to the API.  This is a totally reasonable operation, same as it would be for
Arrays.
>
> The identify function for monads is the monadic lift function -
> Future.accept() in the case of Futures.  The only reason passing the
> identity function in *at all* works is because we have special magic
> that lets authors return non-Futures from the callbacks (which I think
> is a good idea, mind you).  It's not actually an identity function, though.
> The synchronous analog objections don't make sense.  The analogue is
> returning the Error object itself, which could certainly be reasonable at
> times.
> Recursive unwrapping is like making "return new Error()"
> identical to "throw new Error()".  I don't even understand the
> attempted analogy with f() and g() - chaining takes care of unwrapping
> in all reasonable cases like that.  Similarly, I don't think the Stack
> Frame analogy has been well- thought-out - chaining Futures is the
> analogy to stack frames, and that works just fine.
>
> I'm not sure what the Parametricity Argument is.
>
> However, all of this falls before the simple fact that recursive
> unwrapping means that *no one can ever create any object with a
> .then() method on it ever again*.  If .then() is treated as the normal
> monadic operation over Futures (that is, it unwraps one layer of its
> return value), then you can safely return objects with a .then()
> method by wrapping them in a Future with a method like
> Future.accept().  (You can safely do this to *all* values unless
> you're explicitly asking for chaining to happen.)
>
 
Given the collision with possible existing uses of "then", it might be better to
either use a symbol to brand an object as a thenable, or use a symbol to
define a compatible then (or done) -like method similar to @iterator. It
would only be necessary to import and apply the symbol to interoperate with
a native Future, and subclasses of Future would implicitly have support.
Alternatively, only "recursively unwrap" native Futures or Future subclasses,
and require an explicit coercion using something like Future.of.

Ron

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


  1   2   >