Re: await on synchronous functions

2015-07-17 Thread Chris Toshok
I think we're confusing two different cases here:

1) usage of `await` in the body of a function that is not itself marked as
`async`
2) usage of `await f()` where `f` is not marked as `async`.

1 is easy to mark as an early error (and should be imo).  2, not so much
(and is what Mark was asking?)

-c


On Fri, Jul 17, 2015 at 12:30 PM, Ben Newman benja...@cs.stanford.edu
wrote:

 If we stick with the rule that await is only regarded as a keyword if it
 appears in the body of an async function, then await x without async is
 simply a syntax error, and we can avoid having to answer this question!

 That said, perhaps a more natural way of handling wayward await
 expressions is to treat them as referring to the closest enclosing async
 function on the call stack (not necessarily the immediate enclosing
 function), throwing an exception if there is no async function on the
 stack. Then any await expression would delay the resolution of the Promise
 returned by whatever async function is currently executing. The
 same-function-body syntax restriction is a special case of that more
 general model (and notably easier to implement by transpiling to
 generators!).

 Generalizing async/await in this way turns out to be equivalent to
 introducing coroutines into the language, and while I would love to see
 that happen one day (it would greatly simplify writing parallel forEach
 loops, for example), it would require substantial changes to the execution
 model of the language.

 Here are some slides from a talk I gave earlier this year about the
 benefits and pitfalls of coroutines, in case you're interested:
 http://benjamn.github.io/goto2015-talk
 On Fri, Jul 17, 2015 at 11:35 AM Andrea Giammarchi 
 andrea.giammar...@gmail.com wrote:

  Think about a large program where you refactor a single async function
 to no longer be async

 did that ever happened in the history of logic? I am actually curious to
 understand a single valid case where that would be a solution to any
 problem.

 Apologies if I can't see your point but we've been talking about Promise
 must Promise so much this answer was absolutely unexpected.

 Thanks for any sort of clarification

 On Fri, Jul 17, 2015 at 7:27 PM, Tom Van Cutsem tomvc...@gmail.com
 wrote:

 2015-07-17 19:41 GMT+02:00 Andrea Giammarchi 
 andrea.giammar...@gmail.com:

 If I might, if there's one thing that has never particularly shone in
 JS, that is consistency.

 I see only two possibilities here: 1) it throws with non Promises 2) it
 Promisify anything that's not a Promise as if it was a
 `Promise.resolve(1)` ... but since there's too much magic in the second
 point, I'd rather stick with the first one.


 I would be highly in favor of (2). Think about a large program where you
 refactor a single async function to no longer be async. Then I see no
 reason why I should be forced to refactor all of its callers to remove the
 await keyword. Going from sync to async requires refactoring because you're
 introducing new potential interleaving hazards, but any code that is
 already prepared to work with async functions (or promises in general)
 should work equally fine on immediately resolved promises.

 regards,
 Tom




 Just my quick thoughts

 Best Regards

 On Fri, Jul 17, 2015 at 6:33 PM, Kevin Smith zenpars...@gmail.com
 wrote:

 I know the spec for this isn't finalized, but what is the current
 direction for the behaviour when await is used on a function that is not
 marked async and doesn't return a Promise? Should it run immediately or
 wait for the next turn of the event loop?


 More generally, the question is: what should await do for non-promises?

 await 1;

 Should it force a job to be queued?

 ___
 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


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


Re: Removal of WeakMap/WeakSet clear

2014-12-03 Thread Chris Toshok
On Thu, Nov 27, 2014 at 10:40 AM, Allen Wirfs-Brock al...@wirfs-brock.com
wrote:


 This is the end of my assumed inverted WC design and why I assert that a
 clear method is incompatible with it.


Couldn't this be solved by adding a little state (a monotonically
increasing 'generation' counter) to the WC?  Then, something like this:

```js
WC.prototype.clear = function() { this.generation ++; }
WC.prototype.has = function(k) {
  var slot = getWCSlot(k, this);
  return slot  slot.generation == this.generation;
};
WC.prototype.set = function(k, v) {
  var slot = getWCSlot(k, this);
  if (slot) {
// update the slot's information (including generation)
slot.generation = this.generation;
slot.value = v;
  }
  else {
k[@@weakContainers][this] = { generation: this.generation, value: v };
  }
};
WC.prototype.get = function(k) {
  var slot = getWCSlot(k, this);
  if (!slot) return undefined;
  if (slot.generation != this.generation) {
// purge the key's slot for this weakmap
delete k[@@weakContainers][this];
return undefined;
  }
  return slot.value;
};
```

Then clear()'s description can be changed to (if it wasn't this already)
simply: There is no way to retrieve values corresponding to keys added
prior to the clear()
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Removal of WeakMap/WeakSet clear

2014-12-03 Thread Chris Toshok
A more compact implementation occurred to me during my commute:  just have
an internal slot in the WC that it uses when looking up values, instead of
the WC reference itself.

This has the downside of not being able to purge old slots on calls to
has/get, but removes the possibility of overflow (if 'generation' is a
uint32, e.g)

```js
WC.prototype.clear = function() { this.[[WCIdentity]] = new object(); }
WC.prototype.has = function(k) {
  var slot = GetWCSlot(k, this.[[WCIdentity]]);
  return slot !== undefined;
};
WC.prototype.set = function(k,v) {
  var slot = GetWCSlot(k, this.[[WCIdentity]]);
  if (!slot)
slot = CreateWCSlot(k, this.[[WCIdentity]]);
  slot.value = v;
};
WC.prototype.get = function(k) {
  var slot = GetWCSlot(k, this.[[WCIdentity]]);
  return slot  slot.value;
};
```

On Wed, Dec 3, 2014 at 9:20 AM, Chris Toshok tos...@gmail.com wrote:

 On Thu, Nov 27, 2014 at 10:40 AM, Allen Wirfs-Brock al...@wirfs-brock.com
  wrote:


 This is the end of my assumed inverted WC design and why I assert that a
 clear method is incompatible with it.


 Couldn't this be solved by adding a little state (a monotonically
 increasing 'generation' counter) to the WC?  Then, something like this:

 ```js
 WC.prototype.clear = function() { this.generation ++; }
 WC.prototype.has = function(k) {
   var slot = getWCSlot(k, this);
   return slot  slot.generation == this.generation;
 };
 WC.prototype.set = function(k, v) {
   var slot = getWCSlot(k, this);
   if (slot) {
 // update the slot's information (including generation)
 slot.generation = this.generation;
 slot.value = v;
   }
   else {
 k[@@weakContainers][this] = { generation: this.generation, value: v };
   }
 };
 WC.prototype.get = function(k) {
   var slot = getWCSlot(k, this);
   if (!slot) return undefined;
   if (slot.generation != this.generation) {
 // purge the key's slot for this weakmap
 delete k[@@weakContainers][this];
 return undefined;
   }
   return slot.value;
 };
 ```

 Then clear()'s description can be changed to (if it wasn't this already)
 simply: There is no way to retrieve values corresponding to keys added
 prior to the clear()

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


Re: ModuleImport

2014-06-19 Thread Chris Toshok
On Thu, Jun 19, 2014 at 7:13 AM, Calvin Metcalf calvin.metc...@gmail.com
wrote:

  With this idea you cannot look at the import statement to see if the
 imported binding is a module instance object or not.

 the flip side of that is that you don't need to know whether something is
 a default export or a named export to import it e.g.



and elsewhere James Burke wrote:



 1) Only allow export default or named exports, not both.


I wrote about both of these issues here the other day:


https://blog.toshokelectric.com/too-little-too-late-my-thoughts-on-es6-modules/

IMO you can't really implement Calvin's suggestion without making
default+named exports an early error, since you don't know where the
bindings should come from if a module contains both.

This would be great from the perspective of decoupling import/export
syntaxes.  But mutable bindings gum up the works, in that they provide
another avenue for anti-refactoring pressure to flow from module consumer
to module author, and the proposed syntax changes here (not by David) as
well as in my post would make their behavior even more of a hazard.  The
syntaxes need to remain coupled in some form because you really *do* want
to know if you're getting a mutable binding or not.

David's `import * as foo from 'foo'` proposal gets us close enough to the
ideal of what's possible now, that it's definitely a +1 here.

ES6 favors the single/default export style, and gives the sweetest syntax
 to importing the default


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


Re: ModuleImport

2014-06-19 Thread Chris Toshok
On Thu, Jun 19, 2014 at 6:57 AM, Erik Arvidsson erik.arvids...@gmail.com
wrote:


 On Thu, Jun 19, 2014 at 6:41 AM, Calvin Metcalf calvin.metc...@gmail.com
 wrote:

 One other option could be for import name from 'path'  to resolve to the
 module body there is no default export, thanks to the static analysis
 you'll always know when default is present.

 That is a refactoring hazard. If the module changes to add/remove the
 default export the import will still succeed but the value is either a
 module instance object or anything:

 // a.js
 export default class C { ... }

 // importer.js
 import A from './a';
 new A();

 Now a.js changes.

 // a.js V2
 export class C { ... }

 // importer.js
 import A from './a';
 new A();  // TypeError: A is not a function

 With this idea you cannot look at the import statement to see if the
 imported binding is a module instance object or not.


I think you're example misses one point - The module author changed the
exported api, going from exporting a function named C to exporting an
object with a property named C.  Problems caused by this refactoring would
exist regardless of Calvin's suggestion.

Calvin's suggestion would allow the following refactoring to be done by the
module author without impacting his users, something not possible with
current ES6:

```js
// a.js V1
export default { C: class C { ... } }

// a.js V2
export class C { ... }
```

The refactoring hazard is real, but exists iff the module consumer uses
implicit exports (i.e. an Object.prototype method with the above default
export).  This is another reason why the named export form is better -
everything is explicit.  IMO the only good reason to use default export is
to export a single function.

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


Re: ModuleImport

2014-06-19 Thread Chris Toshok
On Thu, Jun 19, 2014 at 10:53 AM, Matthew Robb matthewwr...@gmail.com
wrote:

 What if the `import module/id;` form was an expression that evaluated to
 the module instance object.

 This means everything stays as it is now except we remove the ModuleImport
 form and if you want to use the module instance object you can do: `var foo
 = import foo;`. You could also do `var { bar } = import foo;`


This is essentially identical to System.get(foo), other than the
restriction on the argument being a string.  It lends itself to imperative
code when what you're after is a declarative syntax.

Making it an expression also means it's not a toplevel form in the grammar,
and so you could do things like this:

function foo() {
  if (someCondition)
return import module1;
  else
return import module2;
}

or even similar to your examples:

var { bar } = someCondition ? import foo : import bar;

which would make precise and static computation of the set of imports
impossible, and likely complicate module resolution as well.

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


Re: ModuleImport

2014-06-19 Thread Chris Toshok
On Thu, Jun 19, 2014 at 11:06 AM, Erik Arvidsson erik.arvids...@gmail.com
wrote:

 On Thu, Jun 19, 2014 at 1:23 PM, Chris Toshok tos...@gmail.com wrote:

 On Thu, Jun 19, 2014 at 6:57 AM, Erik Arvidsson erik.arvids...@gmail.com
  wrote:


 On Thu, Jun 19, 2014 at 6:41 AM, Calvin Metcalf 
 calvin.metc...@gmail.com wrote:

 One other option could be for import name from 'path'  to resolve to
 the module body there is no default export, thanks to the static analysis
 you'll always know when default is present.

 That is a refactoring hazard. If the module changes to add/remove the
 default export the import will still succeed but the value is either a
 module instance object or anything:

  // a.js
 export default class C { ... }

 // importer.js
 import A from './a';
 new A();

 Now a.js changes.

 // a.js V2
 export class C { ... }

 // importer.js
 import A from './a';
 new A();  // TypeError: A is not a function

 With this idea you cannot look at the import statement to see if the
 imported binding is a module instance object or not.


 I think you're example misses one point - The module author changed the
 exported api, going from exporting a function named C to exporting an
 object with a property named C.  Problems caused by this refactoring would
 exist regardless of Calvin's suggestion.


 With the current spec this is a compile time error since a.js (V2) does
 not export default.


Correct, but:

```js
// a.js
export default class C { ... }

// a.js V2
export default { C: class C { ... } }
```

The author changed the shape of the api here as well, preserving default
export.  Hazards abound once you have an importer.  That's what I meant by
problems caused by that sort of refactoring existing regardless of Calvin's
suggestion - if the shape changes there's nothing you can do in the general
case.

By adopting something like Calvin's suggestion we can remove a possible
module-side hazard, caused by the fact that the shape of an api
artificially differs between default export and named exports.




 Calvin's suggestion would allow the following refactoring to be done by
 the module author without impacting his users, something not possible with
 current ES6:

 ```js
  // a.js V1
 export default { C: class C { ... } }


 But this is the thing we are trying hard to have people never do.


What exactly is it we're trying to have people do?  never export more than
1 thing?  or never export an object literal, instead favoring
Object.create(null, { })?

-chris




 // a.js V2
 export class C { ... }
 ```

 The refactoring hazard is real, but exists iff the module consumer uses
 implicit exports (i.e. an Object.prototype method with the above default
 export).  This is another reason why the named export form is better -
 everything is explicit.  IMO the only good reason to use default export is
 to export a single function.

 -chris




 --
 erik

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


Re: Re: Rationale for dropping ModuleImport syntax?

2014-06-12 Thread Chris Toshok
On Thu, Jun 12, 2014 at 3:46 AM, Brian Di Palma off...@gmail.com wrote:

 Is there anything preventing the addition of a ModuleImport like
 affordance at a later stage (e.g. ES7)?


ModuleImport is the only way (in syntax) to achieve CommonJS `require`
behavior on the consumer-side when a module author exclusively uses
multiple exports.

Its lack will force existing module maintainers to export as small a set as
possible - likely either a single identifier - so that they can service the
existing identifier-as-namespace convention CommonJS forces.

Given that there's no real syntactic difference between single identifier
export and default export, I would imagine default export would win since
then you get:  `import _ from 'underscore'` instead of import { _ } from
'underscore'`.

Related to some other comments made in this thread, I think static
 verification errors are a great idea.
 I'd also like to echo the comments that ES6 modules seem well
 designed, looking forward to native implementations.


I definitely agree.  I think the semantics and specification are awesome.
 And having syntax at all is *huge* for tooling and aot/static compilers.

The ModuleImport syntax can be bikeshedded until the cows come home.  It's
not important (to me).  What's important is that there is syntax to get at
its functionality, not imperative code.

IMO the only real issue is the tight coupling between syntax used to import
and syntax used to export.  Why as a module consumer should the module
author's choice dictate which syntax I'm forced to use?  And why as a
module author should the syntax my users want to use dictate how I have to
export my module?  If syntaxes were decoupled, ModuleImport could go away
and we wouldn't lose the functionality, it would simply be `import _ from
'underscore'`.

I don't think it's outlandish, the possibility that a large enough portion
of the community will decide on a single import syntax as best, and
network effects will result in it going from best to only.

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


Re: Rationale for dropping ModuleImport syntax?

2014-06-09 Thread Chris Toshok
Pirouette also has many exports per module for its bindings:

E.g.
https://github.com/toshok/pirouette/blob/master/bindings/uikit.js.

I use both import-{}-from (with many imported bindings) and module-from forms, 
tending toward the former in framework code and the latter in application code.

The fact that the both forms can be accommodated from a single export form is 
the key for me.

-c

 On Jun 9, 2014, at 8:36 AM, Caridy Patino car...@gmail.com wrote:
 
 My perspective here is that there are not too many modules (in nodejs) that 
 rely on more than a handful of exports from a particular module, we are 
 actively working on validating this using esprima in a large set of npm 
 modules. If this is true, we should be just fine with specific imports, and 
 for the edge cases, an imperative form should be sufficient.
 
 For now, I will ask you all to try to find a modules that are using too many 
 exported methods from one of its imported modules, you will be suprise how 
 hard it is too find those. 
 
 /caridy  
 
 
 On Mon, Jun 9, 2014 at 11:27 AM, Axel Rauschmayer a...@rauschma.de wrote:
 As an aside, it is yet to be seen whether the default export thing is the 
 best way, or the bad part itself.  We don't have the real world experience 
 yet to answer that.
 
 I’d even argue that they led to the predicament that we are currently in.
 
 If the default export didn’t look like “the module”, things would, in my 
 opinion, be easier to understand:
 
 ```js
 import _ from Underscore;
 import { flatten, union } from Underscore;
 import default someFunction from single_function_module;
 ```
 
 -- 
 Dr. Axel Rauschmayer
 a...@rauschma.de
 rauschma.de
 
 
 
 
 ___
 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: Rationale for dropping ModuleImport syntax?

2014-06-09 Thread Chris Toshok
That particular use of module-from is a little special. @objc_internal is a 
native module. Once ejs supports enumerating multiple exports from native 
modules I'll be switching that to an import-{}-from.

An example of use would be my toy test applications that consume the modules:

https://github.com/toshok/echo-js/blob/master/test/osx-test/helloosx.js

This uses the import-{}-from syntax and as you can see it's getting rather long 
for appkit (and it only has a window, a button, and a table view).  In my other 
toy apps I've switched exclusively to module-from to keep things from getting 
out of hand while I work. I thought I'd also added an iOS test to the git repo, 
but apparently I haven't - will rectify today.

I would also suggest that supporting both forms allows for better early 
prototyping (module-from) when you don't know exactly what you'll be pulling 
in, with the optional upgrade to potentially faster (definitely faster in ejs 
currently) import-{}-from form later when your code matures, all while 
maintaining easy static checking.

 On Jun 9, 2014, at 9:26 AM, Caridy Patino car...@gmail.com wrote:
 
 Chris, the number of exports is not relevant, and in fact, there is no way to 
 export all members in one go, which aligns well with the proposal to remove 
 the way to import an object with all members. check the consumers of the 
 `uikit` module, and count how many of those exported methods are used in a 
 single module. In fact, this repo is consistent with what we have been 
 saying. If you look at 
 https://github.com/toshok/pirouette/blob/master/bindings/objc.js, it uses 
 `module objc_internal from '@objc_internal';`, then it uses 5 methods 
 exported by that module, which should not be a pain to declare them explicit 
 as imports.
 
 
 On Mon, Jun 9, 2014 at 12:18 PM, Chris Toshok tos...@gmail.com wrote:
 Pirouette also has many exports per module for its bindings:
 
 E.g.
 https://github.com/toshok/pirouette/blob/master/bindings/uikit.js.
 
 I use both import-{}-from (with many imported bindings) and module-from 
 forms, tending toward the former in framework code and the latter in 
 application code.
 
 The fact that the both forms can be accommodated from a single export form 
 is the key for me.
 
 -c
 
 On Jun 9, 2014, at 8:36 AM, Caridy Patino car...@gmail.com wrote:
 
 My perspective here is that there are not too many modules (in nodejs) that 
 rely on more than a handful of exports from a particular module, we are 
 actively working on validating this using esprima in a large set of npm 
 modules. If this is true, we should be just fine with specific imports, and 
 for the edge cases, an imperative form should be sufficient.
 
 For now, I will ask you all to try to find a modules that are using too 
 many exported methods from one of its imported modules, you will be suprise 
 how hard it is too find those. 
 
 /caridy  
 
 
 On Mon, Jun 9, 2014 at 11:27 AM, Axel Rauschmayer a...@rauschma.de wrote:
 As an aside, it is yet to be seen whether the default export thing is 
 the best way, or the bad part itself.  We don't have the real world 
 experience yet to answer that.
 
 I’d even argue that they led to the predicament that we are currently in.
 
 If the default export didn’t look like “the module”, things would, in my 
 opinion, be easier to understand:
 
 ```js
 import _ from Underscore;
 import { flatten, union } from Underscore;
 import default someFunction from single_function_module;
 ```
 
 -- 
 Dr. Axel Rauschmayer
 a...@rauschma.de
 rauschma.de
 
 
 
 
 ___
 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