Re: ModuleImport

2014-07-04 Thread Jussi Kalliokoski
On Thu, Jul 3, 2014 at 9:05 PM, Brendan Eich bren...@mozilla.org wrote:

 Jussi Kalliokoski wrote:

 So sometimes someone can need it, so we must have good support? Is that
 how we operate these days?


 Cool down a minute :-|.


Heh, the internet is a funny place when it comes to interpreting emotion;
I've actually been very calm the whole time. ;D


 JS is a mature language on a big rich-and-messy evolving platform-set
 (browser JS, Node.js, other embeddings). We don't preach only majority use
 cases or there should be only one way to do it -- more TIMTOWDI or
 TimToady Bicarbonate:

 http://en.wikipedia.org/wiki/There%27s_more_than_one_way_to_do_it

 JS systems start small and grow. Modules often merge, split, merge again.
 Cycles happen in the large. ES6 modules address them, they were always a
 design goal among several goals.


I'm well aware, to me it looks like cycles are the defining feature of the
module system on which other features have been built on. The reason this
is a problem is because the requirement of cyclic dependencies not only
complicates the API surface, reasoning about it and implementations, it
also excludes a lot of features.

For example, if we look at the problem of optional dependencies (which,
btw, unlike cyclic dependencies are an extremely common corner case,
especially on the web, and can't really be refactored away) is not that you
can't load things dynamically, because you can, but in the fact that
importing a module is async but initializing and declaring is not, it's
static to support mutable bindings magic (that are required for transitive
cyclic dependencies) and compile-time errors.

Now, let's have a hypothetical change to the module system. Let's say that
we allow only exporting one thing, and that one thing can be any value.
When you import it, it's like assigning a variable, except that resolving
the value you are assigning to is done async at compile time. Like:

// somewhere.js

export {
  something: function something () {}
};

// doSomethingElse.js
import { something } from somewhere;
export function doSomethingElse () {};

Benefit #1: No module meta object crap, the only new concept needed to
understand this is compile-time prefetching.
Benefit #2: No special destructuring syntax (since you're doing normal
destructuring on a normal value).

Cool, but we broke cyclic dependencies without fixing optional dependencies:

// optional dependency here
var fasterAdd = System.import(fasterAdd);
var basicAdd = function (a, b) {
  return a + b;
};

// because there's no async initialize, we have to impose an async
interface for an otherwise sync operation
export function add (a, b) {
  return fasterAdd
.catch( = basicAdd )
.then( (addMethod) = addMethod(a, b) );
};

However, with this design, we can allow exporting a promise of what we want
to export, thus deferring the import process until that promise is resolved
or rejected:

var basicAdd = function (a, b) {
  return a + b;
};

export System.import(fasterAdd)
  .catch( = basicAdd );

And there you have it, voilá.

Benefit #3: See #1, if you don't want to, you don't even have to comprehend
compile-time prefetching anymore. It's just optimization sugar.
Benefit #4: No need to impose async interfaces for inherently sync
operations just because the initialize phase is not async while loading is.
Benefit #5: You can do stuff like async feature detects in the initialize
phase, something that is completely broken in existing module systems (you
*can* do this with RequireJS through some effort, but I'm not sure it's
officially supported or part of AMD).
Benefit #6: High compatibility with existing module systems, including edge
cases, providing a solid foundation for transpiling legacy modules to the
new system. See some sketches I made yesterday when playing around with the
idea: https://gist.github.com/jussi-kalliokoski/6e0bf476760d254e5465
(includes an example of how you could implement localforage if the platform
dependencies were provided as modules).
Benefit #7: Addresses the issue of libraries depending on more than just JS:

import {loadImages, importStylesheets} from fancy-loader;

var myModule = { ... };

export Promise.all([
  loadImages([foo.jpg, bar.png]),
  importStylesheets([style.css])
]).then( = myModule );

There's probably more that didn't come to my mind. So, this would support
pretty much all the features of the existing solutions and more. Just not
cyclic dependencies. At all.

Now, we could of course try to add this as an afterthought to the current
design by letting individual exports be promises, but in order to preserve
transitive cyclic dependencies in that case, you'd have to wait for the
promise of that to resolve when the importing module accesses the imported
binding, not only causing execution to yield to the event loop unexpectedly
(which is what we're trying to avoid with async functions) but also makes
it transitive only most of the time, ending up with cyclic dependencies
that 

Re: ModuleImport

2014-07-04 Thread Jussi Kalliokoski
On Fri, Jul 4, 2014 at 10:19 AM, Jussi Kalliokoski 
jussi.kallioko...@gmail.com wrote:


 On Thu, Jul 3, 2014 at 9:05 PM, Brendan Eich bren...@mozilla.org wrote:

 Cool down a minute :-|.


I now realize that my tone on this thread hasn't been very considerate, and
apologize if I offended anyone, or even if I didn't.

I don't want anyone to think that I don't respect the work that's been done
to get ES6 modules where they are today. Considering the use cases and
requirements they've been designed for, the design is actually great. My
goal was only to challenge those use cases and requirements and their
priority over other ones, but I failed at conveying that properly. Sorry.

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


Re: Re: ModuleImport

2014-07-03 Thread Jussi Kalliokoski
On Thu, Jul 3, 2014 at 1:29 AM, Brian Di Palma off...@gmail.com wrote:

  The arguments for and against supporting cyclic dependencies seem to be
 academic. I'm yet to see any evidence of their importance in practice nor
 proof they they are fundamental ... or not.

 Transitive cyclic dependencies. I'd say that's the case that was in
 the minds of the authors of the module system.
 In large codebases those can happen and a module system that does not
 handle them gracefully would be poor.

 Support for them is needed, and what CommonJS has is not good enough.
 They are acknowledged in the modules documentation for node
 http://nodejs.org/api/all.html#all_cycles
 This does not mean they are recommended, the same holds true for ES6
 modules.

 It is an acceptance of the reality of complex and large codebases that
 sometimes cyclic dependencies can occur.


So sometimes someone can need it, so we must have good support? Is that how
we operate these days?


 It boils down to this.

 You can import a dependency in three ways

 import MyClass from 'MyClass';
 import {MyClass} from 'MyClass';
 module myClass from 'MyClass';


And (in the same order):
System.import(MyClass).then(function (MyClassModule) {
  // I don't actually know how someone would even access the default
exports from the module object unless in case of default exports there is
no module object, just the default exports as the module.
  var MyClass = MyClassModule;
});

System.import(MyClass).then(function (MyClassModule) {
  var { MyClass } = MyClassModule;
});

System.import(MyClass).then(function (MyClassModule) {
  var myClass = MyClassModule;
});

var MyClass = System.get(MyClass);
var {MyClass} = System.get(MyClass);
var myClass = System.get(MyClass);



 That's one too many ways for the simplest module system that fulfills
 all requirements.

 import MyClass from 'MyClass';
 import {MyClass} from 'MyClass';
 import * as myClass from 'MyClass';

 Is not the fix.

 The confusion stemmed from the first production not the last.


I agree. Thanks, I'm actually no longer even indifferent towards default
exports but I also think it should go.


 Perfection is achieved, not when there is nothing more to add, but
 when there is nothing left to take away.

 B.
 ___
 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: ModuleImport

2014-07-03 Thread Brian Di Palma
 So sometimes someone can need it, so we must have good support? Is that how 
 we operate these days?

Imagine a large codebase which already has transitive cyclic dependencies.
If the module system has poor support for them it might still work
with them until one day a developer reordered the import statements.
How would you feel if such a simple operation caused you issues?

Or upgrading to the latest version of a popular utility toolchain like
lo-dash could introduce an issue purely because the upgrade created a
transitive cyclic dependency.
And the fix for that would be to reorder your import statements and
add comments in your module telling people not to change the order.
Again, how would you feel?

TC39 has decided to spare us all those special moments by including
good cyclic dependency support.

 // I don't actually know how someone would even access the default exports 
 from the module object

Like so,

```
System.import(MyClass)
.then(function (myClassModule) {
myClassModule.default
});
```

Default import and exports are purely sugar over

```
import {default as MyClass} from 'MyClass';
```

It saves you a few character typing out when importing from legacy
module system.

```
import MyClass from 'MyClass';
```

Those two are the same thing.

From birth the brand new module system is going to have this
superfluous appendage to support module systems that 10 years from now
people will struggle to remember.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Re: ModuleImport

2014-07-03 Thread Jussi Kalliokoski
On Thu, Jul 3, 2014 at 11:41 AM, Brian Di Palma off...@gmail.com wrote:

  So sometimes someone can need it, so we must have good support? Is that
 how we operate these days?

 Imagine a large codebase which already has transitive cyclic dependencies.
 If the module system has poor support for them it might still work
 with them until one day a developer reordered the import statements.
 How would you feel if such a simple operation caused you issues?


Happy; finally having a good motivator to refactor and get rid of the
cyclic dependencies, at least in that compartment.


 Or upgrading to the latest version of a popular utility toolchain like
 lo-dash could introduce an issue purely because the upgrade created a
 transitive cyclic dependency.
 And the fix for that would be to reorder your import statements and
 add comments in your module telling people not to change the order.
 Again, how would you feel?


Angry at lo-dash for breaking backwards compatibility, then I'd revert the
upgrade and file a bug against it. I'd probably also consider whether
lo-dash were in this imaginary case something I want to depend on given
that for a utility library they need cyclic dependencies. I'd also be happy
that the module system made this obvious.

But I get your point since I'm well aware that my thoughts are likely not
to be a very good representation of how most people would feel.

However, I still don't think it's something worth making other sacrifices
over.


 Default import and exports are purely sugar over

 ```
 import {default as MyClass} from 'MyClass';
 ```

 It saves you a few character typing out when importing from legacy
 module system.

 ```
 import MyClass from 'MyClass';
 ```

 Those two are the same thing.


Ughh, I see. Not cool.


 From birth the brand new module system is going to have this
 superfluous appendage to support


Let's not have it. At least not in ES6. Tools like Traceur can support it
for an easier migration path since they already have diverged from ES.next
anyway with all the annotations (for which, off topic, I haven't seen even
a proposal here yet) and stuff.


 module systems that 10 years from now
 people will struggle to remember.


I certainly hope that will be the case, but it's 2014 and people are still
implementing banking with Cobol, security protocols with C++ and website
cryptography with Java applets.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Re: ModuleImport

2014-07-03 Thread John Barton
On Thu, Jul 3, 2014 at 2:31 AM, Jussi Kalliokoski 
jussi.kallioko...@gmail.com wrote:

  Tools like Traceur can support it for an easier migration path since they
 already have diverged from ES.next anyway with all the annotations (for
 which, off topic, I haven't seen even a proposal here yet) and stuff.


Jussi, I would appreciate a bug report on the Traceur github project
pointing to information that makes you think this statement is correct. We
consider divergence from ES.next to be a bug and do not support any feature
outside of the proposal from TC39.   Our project does provides great
technology that has been used to develop migration tools, annotation
experiments, and stuff. All of that comes on other projects or under
opt-in flags on traceur.

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


Re: Re: ModuleImport

2014-07-03 Thread Jussi Kalliokoski
On Thu, Jul 3, 2014 at 5:42 PM, John Barton johnjbar...@google.com wrote:

 On Thu, Jul 3, 2014 at 2:31 AM, Jussi Kalliokoski 
 jussi.kallioko...@gmail.com wrote:

  Tools like Traceur can support it for an easier migration path since
 they already have diverged from ES.next anyway with all the annotations
 (for which, off topic, I haven't seen even a proposal here yet) and stuff.


 Jussi, I would appreciate a bug report on the Traceur github project
 pointing to information that makes you think this statement is correct. We
 consider divergence from ES.next to be a bug and do not support any feature
 outside of the proposal from TC39.


Annotations are marked as experimental, but I filed a bug anyway to either
get a proposal or update the wiki to inform that there's no official spec
or proposal for it: https://github.com/google/traceur-compiler/issues/1156
;)


 Our project does provides great technology that has been used to develop
 migration tools, annotation experiments, and stuff. All of that comes on
 other projects or under opt-in flags on traceur.


Exactly, and that's how it could be done in traceur.

- Jussi


 jjb

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


Re: ModuleImport

2014-07-02 Thread Jussi Kalliokoski
On Tue, Jul 1, 2014 at 10:28 PM, Kevin Smith zenpars...@gmail.com wrote:


  As such, we are balancing the marginal user experience gains of
 export-overwriting against the better support for circular dependencies
 of real modules.


 Another way of looking at it:

 Being in control of the language, you can always invent new sugar to
 optimize user experience (within limits) when real usage data proves its
 worth.  But the core model can't be changed.

 As such, it seems like it would be better to err on the side of making the
 core model simple and solid, leaving minor UX optimizations to future
 syntax.


But it's neither simple nor solid. It's overtly complicated to support
features that shouldn't be there.

Sorry in advance for the tone of this message, it is quite negative. But
the intent is constructive. To me modules are the most anticipated feature
in ES6 and I've been closely following the discussion and the proposal's
evolution and I've been extremely thrilled. Finally we could have a chance
of alleviating the situation of having a ton of non-intercompatible
different module loaders. I haven't contributed much to the discussion
since I liked the overall direction. However, now that I've been actually
using the modules for a while with a couple of different transpilers, it's
become obvious that the design is inherently broken (not the fault of the
transpilers, they are actually probably better in some aspects than the
real thing), and in order for ES modules to help the situation instead of
making it worse, it needs to be better than the existing solutions.

The core unique selling points of ES6 modules as opposed to the other
module loading systems:

* Language built-in: the strongest point. This makes sure that most tooling
should support the feature out of the box and that module authors are more
inclined to provide their modules in this format. But the design can be
whatever and this point will still hold true, so no points to the design
here.
* (Reliably) statically analyzable syntax. This is my favourite feature and
really awesome. Allows engine to fetch next modules while the current one
is still being parsed, and tooling to better understand what the code does.
However, this would hold true even if all we standardized was syntactic
sugar on top of requirejs.
* Cyclic dependencies: First of all, this is not a feature you want to
necessarily encourage. It looks good in academia, but in my career I've yet
to see real world code that would benefit more from cyclic dependencies
more than refactoring. Not to mention that having cyclic dependencies have
been possible in global scope modules since LiveScript, and is possible in
CommonJS as well if you do a little DI:
https://gist.github.com/jussi-kalliokoski/50cc79951a59945c17a2 (I had such
a hard time coming up with an example that could use cyclic dependencies
that I had to dig the example from modules examples wiki). And honestly I
don't think it's a feature that deserves to be easier to do than my
example, and especially not worth making other design compromises for.
* Mutable bindings: This will make a good chapter in a future edition of
JavaScript: The bad parts, along with being able to redefine undefined. You
can have mutable bindings in other module systems as well, just reassign
something in your exports and then your consumer uses the exports property
directly. A lot of WTFs avoided and even doing it like that will ring alarm
bells in code review.
* Compile-time errors: This not a feature, it's a bug. Try finding a
website that doesn't somewhere in its code check for whether you have a
feature / module available, i.e. optional dependencies. Some examples:
Angular has jQuery as an optional dependency; spritesheet generator modules
for node that have multiple engines as optional dependencies because some
of them may be native modules that don't compile on all platforms. Also
things get worse if platform features are implemented as modules. Let's say
things like localStorage, IndexedDB and friends were provided as modules
and as a result, things like localforage would either not exist or would be
infinitely more complex. Just look at github search for keywords `try` and
`require`
https://github.com/search?l=javascriptq=try+requireref=cmdformtype=Code
to see how widely used the pattern of wrapping a module load in a try-catch
is.

Now let's look at some things that tip the odds into existing solutions
favor:

* Massive amount of existing modules.
* Existing large-scale user-bases.
* Node has stated that the core will always be CommonJS, meaning that on
node, in order to use ES6 modules, you'll have to be using two different
module systems which doesn't sound like a thing that people would do unless
there's proven benefits.
* Completely dynamic. Now, I know there are people that think that this
isn't not good, but it is. It gives you a lot of power when debugging
things or playing around with new things (something I haven't seen
discussed 

Re: ModuleImport

2014-07-02 Thread Kevin Smith


 But it's neither simple nor solid. It's overtly complicated to support
 features that shouldn't be there.


I have to disagree here.  If we drop default imports, then we can describe
the module system like this:

Variables can be exported by name.  Variables can be imported by name.

It doesn't get any more simple than that.  What I mean by solid is that it
has good coverage of the edge cases, meaning primarily cyclic dependencies.


 Sorry in advance for the tone of this message, it is quite negative.


I didn't perceive this as negative.  I think it's quite constructive to
uncover all of the arguments.


 * Massive amount of existing modules.
 * Existing large-scale user-bases.


We've already taken a look at the technical side of interoperability with
old-style modules, and there's no problem there.  What remains, I suppose,
is a sociological argument.  More on that later.


 * Node has stated that the core will always be CommonJS, meaning that on
 node, in order to use ES6 modules, you'll have to be using two different
 module systems which doesn't sound like a thing that people would do unless
 there's proven benefits.


If users want Node core to be exposed as ES6 modules, then the Node
developers will provide it.  It's not some ideological battle - it's about
whatever is good for the platform.  Regarding two module systems at the
same time: more later.

* Completely dynamic. Now, I know there are people that think that this
 isn't not good, but it is. It gives you a lot of power when debugging
 things or playing around with new things (something I haven't seen
 discussed re:modules on this list). One of the greatest things in JS is
 that instead of reading the usually poor documentation, let alone the code,
 of something you want to use you can just load it up in node or the
 developer tools and play around with it. With node, you require() something
 in the repl and you see immediately what it exports. (...edit...) This is
 simply not possible with ES6 modules without a massive boilerplate
 spaghetti with async stuff.


You're right, but I don't think we need objects-as-modules to address
this.  We want a blocking load API for these situations:

1.  Any REPL  (strong)
2.  Server-only programs which don't care about async loading and don't
want the complications (weaker)

In es6now, I provide a `loadModule` function for loading ES6 modules
synchronously in the REPL.  I think Node would want to provide a
synchronous loading method as part of the so-called module meta object.
 That API needs eyes, BTW.


 Given all this, how are we supposed to convince people to use this stuff?
 These concerns are not something that can be fixed later either, they're
 fundamental to the current design.


I don't see any technical problem here.  So let's look at the sociological
argument:

ES6 modules are different from Node/AMD modules, and seem to be at odds
philosophically.  Since Node/AMD modules already have established user
bases, and important members of the Node community are critical, ES6
modules won't be successful at penetrating the market.

Counter-argument:

Take a look at this package:  https://github.com/zenparsing/zen-sh . It's
an experimental ES6 package which allows you to open up a shell and execute
commands using tagged template strings.  I use it at work to automate git
tasks.  It's awesome (but very rough).  It's completely installable using
NPM, today.  I encourage anyone to try it out (you'll need to install es6now
https://github.com/zenparsing/es6now first, though).

It exports a single thing, but that thing is given a name.  It is set up to
work with both `require` and `import`.

Now, the sociological argument says that because it's written as an ES6
module the community will reject this package.  Does that sound plausible
to you?
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-07-02 Thread Calvin Metcalf
circular dependencies in CJS are much easer then that
https://gist.github.com/calvinmetcalf/57be20b8eda0ee8fe6de


On Wed, Jul 2, 2014 at 4:09 AM, Jussi Kalliokoski 
jussi.kallioko...@gmail.com wrote:

 On Tue, Jul 1, 2014 at 10:28 PM, Kevin Smith zenpars...@gmail.com wrote:


  As such, we are balancing the marginal user experience gains of
 export-overwriting against the better support for circular dependencies
 of real modules.


 Another way of looking at it:

 Being in control of the language, you can always invent new sugar to
 optimize user experience (within limits) when real usage data proves its
 worth.  But the core model can't be changed.

 As such, it seems like it would be better to err on the side of making
 the core model simple and solid, leaving minor UX optimizations to future
 syntax.


 But it's neither simple nor solid. It's overtly complicated to support
 features that shouldn't be there.

 Sorry in advance for the tone of this message, it is quite negative. But
 the intent is constructive. To me modules are the most anticipated feature
 in ES6 and I've been closely following the discussion and the proposal's
 evolution and I've been extremely thrilled. Finally we could have a chance
 of alleviating the situation of having a ton of non-intercompatible
 different module loaders. I haven't contributed much to the discussion
 since I liked the overall direction. However, now that I've been actually
 using the modules for a while with a couple of different transpilers, it's
 become obvious that the design is inherently broken (not the fault of the
 transpilers, they are actually probably better in some aspects than the
 real thing), and in order for ES modules to help the situation instead of
 making it worse, it needs to be better than the existing solutions.

 The core unique selling points of ES6 modules as opposed to the other
 module loading systems:

 * Language built-in: the strongest point. This makes sure that most
 tooling should support the feature out of the box and that module authors
 are more inclined to provide their modules in this format. But the design
 can be whatever and this point will still hold true, so no points to the
 design here.
 * (Reliably) statically analyzable syntax. This is my favourite feature
 and really awesome. Allows engine to fetch next modules while the current
 one is still being parsed, and tooling to better understand what the code
 does. However, this would hold true even if all we standardized was
 syntactic sugar on top of requirejs.
 * Cyclic dependencies: First of all, this is not a feature you want to
 necessarily encourage. It looks good in academia, but in my career I've yet
 to see real world code that would benefit more from cyclic dependencies
 more than refactoring. Not to mention that having cyclic dependencies have
 been possible in global scope modules since LiveScript, and is possible in
 CommonJS as well if you do a little DI:
 https://gist.github.com/jussi-kalliokoski/50cc79951a59945c17a2 (I had
 such a hard time coming up with an example that could use cyclic
 dependencies that I had to dig the example from modules examples wiki). And
 honestly I don't think it's a feature that deserves to be easier to do than
 my example, and especially not worth making other design compromises for.
 * Mutable bindings: This will make a good chapter in a future edition of
 JavaScript: The bad parts, along with being able to redefine undefined. You
 can have mutable bindings in other module systems as well, just reassign
 something in your exports and then your consumer uses the exports property
 directly. A lot of WTFs avoided and even doing it like that will ring alarm
 bells in code review.
 * Compile-time errors: This not a feature, it's a bug. Try finding a
 website that doesn't somewhere in its code check for whether you have a
 feature / module available, i.e. optional dependencies. Some examples:
 Angular has jQuery as an optional dependency; spritesheet generator modules
 for node that have multiple engines as optional dependencies because some
 of them may be native modules that don't compile on all platforms. Also
 things get worse if platform features are implemented as modules. Let's say
 things like localStorage, IndexedDB and friends were provided as modules
 and as a result, things like localforage would either not exist or would be
 infinitely more complex. Just look at github search for keywords `try` and
 `require`
 https://github.com/search?l=javascriptq=try+requireref=cmdformtype=Code
 to see how widely used the pattern of wrapping a module load in a try-catch
 is.

 Now let's look at some things that tip the odds into existing solutions
 favor:

 * Massive amount of existing modules.
 * Existing large-scale user-bases.
 * Node has stated that the core will always be CommonJS, meaning that on
 node, in order to use ES6 modules, you'll have to be using two different
 module systems which doesn't sound like a thing that 

Re: ModuleImport

2014-07-02 Thread Kevin Smith
 circular dependencies in CJS are much easer then that
 https://gist.github.com/calvinmetcalf/57be20b8eda0ee8fe6de


Umm...  I would rather call that tricky as hell ; )
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-07-02 Thread Kevin Smith

 circular dependencies in CJS are much easer then that
 https://gist.github.com/calvinmetcalf/57be20b8eda0ee8fe6de


 Umm...  I would rather call that tricky as hell ; )


Besides, it fails if you do `require(./b)`, IIUC.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-07-02 Thread C. Scott Ananian
I agree with everything Jussi wrote.  He gets to the heart of the issue.

The points that have been previously made about bundling modules also
apply to REPLs.  If a module must be in a file, I can't easily define
modules at a REPL prompt.
 --scott
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-07-02 Thread Kevin Smith

 The arguments for and against supporting cyclic dependencies seem to be
 academic. I'm yet to see any evidence of their importance in practice nor
 proof they they are fundamental ... or not.


I wouldn't say that cyclic dependencies are academic, in the sense of not
real.  If they are allowed by the language, they will be used.  I see them
in Python code and I see them in Node modules.  So unless you plan to
disallow them altogether, it makes sense to provide good support, all other
things being equal.

It's an edge case for the module system, to be sure, but we should expect
the module system to have reasonable coverage over the edge cases.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-07-02 Thread Jussi Kalliokoski
On Wed, Jul 2, 2014 at 7:09 PM, John Barton johnjbar...@google.com wrote:


 * (Reliably) statically analyzable syntax. This is my favourite feature
 and really awesome. Allows engine to fetch next modules while the current
 one is still being parsed,


 This isn't true -- all module designs in play require parsing (include of
 course CJS and AMD).


Huh? I wasn't saying that they don't. I mean that with the static syntax
the parser can initiate the request immediately when it hits an import
statement, which is a good thing and not possible with what is out there.
You can of course assume that the require call with a static string does
what you'd expect but then you might end up loading something that was
never actually required but someone had their own require function there
instead that has something else.


 and tooling to better understand what the code does. However, this would
 hold true even if all we standardized was syntactic sugar on top of
 requirejs.


 I don't believe that anyone expects such an outcome.


Heh of course not, that would be horrible; I was referring to the fact that
this is a low-hanging fruit to pick.


  * Cyclic dependencies: First of all, this is not a feature you want to
 necessarily encourage. It looks good in academia, but in my career I've yet
 to see real world code that would benefit more from cyclic dependencies
 more than refactoring. Not to mention that having cyclic dependencies have
 been possible in global scope modules since LiveScript, and is possible in
 CommonJS as well if you do a little DI:
 https://gist.github.com/jussi-kalliokoski/50cc79951a59945c17a2 (I had
 such a hard time coming up with an example that could use cyclic
 dependencies that I had to dig the example from modules examples wiki). And
 honestly I don't think it's a feature that deserves to be easier to do than
 my example, and especially not worth making other design compromises for.


 The arguments for and against supporting cyclic dependencies seem to be
 academic. I'm yet to see any evidence of their importance in practice nor
 proof they they are fundamental ... or not.


True, and that being the case I don't see the reason of putting them on a
pedestal. If they happen to be a nice side effect, that's fine, but I'm
mostly referring to arguments against different proposals using doesn't
support cyclic dependencies.


 * Compile-time errors: This not a feature, it's a bug. Try finding a
 website that doesn't somewhere in its code check for whether you have a
 feature / module available, i.e. optional dependencies. Some examples:
 Angular has jQuery as an optional dependency; spritesheet generator modules
 for node that have multiple engines as optional dependencies because some
 of them may be native modules that don't compile on all platforms. Also
 things get worse if platform features are implemented as modules. Let's say
 things like localStorage, IndexedDB and friends were provided as modules
 and as a result, things like localforage would either not exist or would be
 infinitely more complex. Just look at github search for keywords `try` and
 `require`
 https://github.com/search?l=javascriptq=try+requireref=cmdformtype=Code
 to see how widely used the pattern of wrapping a module load in a try-catch
 is.


 Optional dependency is completely supported by Loader.import().
  Furthermore its promise based API avoids try/catch goop.


Try/catch is far less goop than promises, and furthermore your non-optional
dependencies don't come in as promises, and neither can you define your
module asynchronously and wait to see whether the optional dependency is
available before exposing your interface. If you could define your module
like this it would be less of a problem but still ugly and inferior (in
this specific case) to for example CJS:

import someRequiredDependency from somewhere;

Loader.import(someOptionalDependency)
  .catch(function noop () {})
  .then(function (someRequiredDependency) {
exports function doSomething (foo) {
  if ( someOptionalDependency ) {
return someOptionalDependency(foo + 5);
  } else {
return someRequiredDependency(foo + 2);
  }
};
  });





 Now let's look at some things that tip the odds into existing solutions
 favor:

 * Massive amount of existing modules.
 * Existing large-scale user-bases.
 * Node has stated that the core will always be CommonJS, meaning that on
 node, in order to use ES6 modules, you'll have to be using two different
 module systems which doesn't sound like a thing that people would do unless
 there's proven benefits.


 These points are not relevant since nothing in the current design prevents
 these success stories from continuing.


The two first points are relevant if they decrease the chances of ES6
modules becoming the most used module system (which is obviously a goal
because otherwise we'll just be making things worse by contributing to
fragmentation). The last one is relevant because it 

Re: ModuleImport

2014-07-02 Thread Calvin Metcalf
 You can of course assume that the require call with a static string does
what you'd expect but then you might end up loading something that was
never actually required but someone had their own require function there
instead that has something else.

This is a solved problem actually https://github.com/calvinmetcalf/derequire
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-07-02 Thread John Barton
This seems like a bit too many issues, so let me just correct one
(important) one.


On Wed, Jul 2, 2014 at 2:09 PM, Jussi Kalliokoski 
jussi.kallioko...@gmail.com wrote:

 On Wed, Jul 2, 2014 at 7:09 PM, John Barton johnjbar...@google.com
 wrote:





 Now, I know there are people that think that this isn't not good, but it
 is. It gives you a lot of power when debugging things or playing around
 with new things (something I haven't seen discussed re:modules on this
 list). One of the greatest things in JS is that instead of reading the
 usually poor documentation, let alone the code, of something you want to
 use you can just load it up in node or the developer tools and play around
 with it. With node, you require() something in the repl and you see
 immediately what it exports.


 Loader.get() provides the module.


 Hmm, my bad, I actually thought that Loader.get() works only when the
 module has already been fetched.


Your thought was correct: Loader.get() only works if the module is fetched.
 It was my impression that you were describing a debugging scenario where
the module would be loaded and where you are likely to want to avoid
module-loading since your goal is to debug the live image.



 Well that improves things a lot but that still leaves the disparity
 between what you'd write in actual code and the repl and thus fails to be
 better (in this case) than for example CommonJS.


I expect devtools to support declarative import in their REPL, so the code
you would write is the same.

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


Re: ModuleImport

2014-07-02 Thread Jussi Kalliokoski
On Wed, Jul 2, 2014 at 3:38 PM, Kevin Smith zenpars...@gmail.com wrote:


 But it's neither simple nor solid. It's overtly complicated to support
 features that shouldn't be there.


 I have to disagree here.  If we drop default imports, then we can describe
 the module system like this:

 Variables can be exported by name.  Variables can be imported by name.


FWIW, I don't have a problem with dropping / deferring default exports,
although my personal ideal is that like functions, modules should do one
thing and thus export one thing, but having no default exports doesn't
prevent exporting just one thing.



 It doesn't get any more simple than that.  What I mean by solid is that it
 has good coverage of the edge cases, meaning primarily cyclic dependencies.


The complexity is in having multiple different ways of doing one thing and
introducing new kind of bindings to the language that didn't exist before
to support those edge cases.




 Sorry in advance for the tone of this message, it is quite negative.


 I didn't perceive this as negative.  I think it's quite constructive to
 uncover all of the arguments.


Happy to hear!



 * Massive amount of existing modules.
 * Existing large-scale user-bases.


 We've already taken a look at the technical side of interoperability with
 old-style modules, and there's no problem there.  What remains, I suppose,
 is a sociological argument.  More on that later.


 * Node has stated that the core will always be CommonJS, meaning that on
 node, in order to use ES6 modules, you'll have to be using two different
 module systems which doesn't sound like a thing that people would do unless
 there's proven benefits.


 If users want Node core to be exposed as ES6 modules, then the Node
 developers will provide it.  It's not some ideological battle - it's about
 whatever is good for the platform.  Regarding two module systems at the
 same time: more later.

  * Completely dynamic. Now, I know there are people that think that this
 isn't not good, but it is. It gives you a lot of power when debugging
 things or playing around with new things (something I haven't seen
 discussed re:modules on this list). One of the greatest things in JS is
 that instead of reading the usually poor documentation, let alone the code,
 of something you want to use you can just load it up in node or the
 developer tools and play around with it. With node, you require() something
 in the repl and you see immediately what it exports. (...edit...) This is
 simply not possible with ES6 modules without a massive boilerplate
 spaghetti with async stuff.


 You're right, but I don't think we need objects-as-modules to address
 this.


But depending on how you load the modules (i.e. syntax or Loader API) the
module might end up being an object anyway so it's just confusing if it
sometimes is and sometimes isn't.


 We want a blocking load API for these situations:

 1.  Any REPL  (strong)
 2.  Server-only programs which don't care about async loading and don't
 want the complications (weaker)

 In es6now, I provide a `loadModule` function for loading ES6 modules
 synchronously in the REPL.  I think Node would want to provide a
 synchronous loading method as part of the so-called module meta object.


The term module meta object and simple design don't go hand in hand.


 That API needs eyes, BTW.


Thanks for the reference, I'll take a look at it after having a good
night's sleep first. :)




 Given all this, how are we supposed to convince people to use this stuff?
 These concerns are not something that can be fixed later either, they're
 fundamental to the current design.


 I don't see any technical problem here.  So let's look at the sociological
 argument:

 ES6 modules are different from Node/AMD modules, and seem to be at odds
 philosophically.  Since Node/AMD modules already have established user
 bases, and important members of the Node community are critical, ES6
 modules won't be successful at penetrating the market.

 Counter-argument:

 Take a look at this package:  https://github.com/zenparsing/zen-sh . It's
 an experimental ES6 package which allows you to open up a shell and execute
 commands using tagged template strings.  I use it at work to automate git
 tasks.  It's awesome (but very rough).  It's completely installable using
 NPM, today.  I encourage anyone to try it out (you'll need to install
 es6now https://github.com/zenparsing/es6now first, though).

 It exports a single thing, but that thing is given a name.  It is set up
 to work with both `require` and `import`.

 Now, the sociological argument says that because it's written as an ES6
 module the community will reject this package.  Does that sound plausible
 to you?


No of course not, but why would anyone introduce more complexity to their
project to do what you did? Experimental curiosity is probably your case,
but the only other reason I can think of is sadism, deliberately
fragmenting the platform. In that example, 

Re: Re: ModuleImport

2014-07-02 Thread Brian Di Palma
 The arguments for and against supporting cyclic dependencies seem to be 
 academic. I'm yet to see any evidence of their importance in practice nor 
 proof they they are fundamental ... or not.

Transitive cyclic dependencies. I'd say that's the case that was in
the minds of the authors of the module system.
In large codebases those can happen and a module system that does not
handle them gracefully would be poor.

Support for them is needed, and what CommonJS has is not good enough.
They are acknowledged in the modules documentation for node
http://nodejs.org/api/all.html#all_cycles
This does not mean they are recommended, the same holds true for ES6 modules.

It is an acceptance of the reality of complex and large codebases that
sometimes cyclic dependencies can occur.

It boils down to this.

You can import a dependency in three ways

import MyClass from 'MyClass';
import {MyClass} from 'MyClass';
module myClass from 'MyClass';

That's one too many ways for the simplest module system that fulfills
all requirements.

import MyClass from 'MyClass';
import {MyClass} from 'MyClass';
import * as myClass from 'MyClass';

Is not the fix.

The confusion stemmed from the first production not the last.

Perfection is achieved, not when there is nothing more to add, but
when there is nothing left to take away.

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


Re: Re: ModuleImport

2014-07-02 Thread Rob Sayre
On Wed, Jul 2, 2014 at 3:29 PM, Brian Di Palma off...@gmail.com wrote:

  The arguments for and against supporting cyclic dependencies seem to be
 academic. I'm yet to see any evidence of their importance in practice nor
 proof they they are fundamental ... or not.

 Support for them is needed, and what CommonJS has is not good enough.
 They are acknowledged in the modules documentation for node
 http://nodejs.org/api/all.html#all_cycles
 This does not mean they are recommended, the same holds true for ES6
 modules.

 It is an acceptance of the reality of complex and large codebases that
 sometimes cyclic dependencies can occur.


That's awesome--I didn't know that node had arrived at exactly the same
solution as Firefox did. It even uses the same test file names. Node's
module system has way more users, and Firefox's is twice as old.

Here's the 7-year old test for it:

http://hg.mozilla.org/mozilla-central/annotate/38ecfc3922b8/js/xpconnect/tests/unit/test_recursive_import.js

I wrote that, but I didn't have any conceptual insight. All I did was go
what does python do and made the Mozilla JS engine do that. I think
that's the critical disconnect in this thread--we have the ability to
change the JS implementations, so we're not fenced in by the way JavaScript
currently works. The authors of node.js and Firefox arrived at that
conclusion, anyway.

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


Re: ModuleImport

2014-07-01 Thread Kevin Smith
So I think we've gone over the interoperability argument already.  That is,
with default exports (or module-object-overwriting), you can write
something like this:

import x from some-old-module;

Without default exports, you'll have to use something like one of the
following:

import { exports as x } from some-old-module;
import { default as x } from some-old-module;
import { _ as x } from some-old-module;

The user experience is a little better with default exports, but we
shouldn't be overly concerned with optimizing the loading old-style
modules.  The experience without default exports is good enough.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-07-01 Thread Kevin Smith
There are three arguments for default exports:

1.  Anonymous exports are a value-adding feature, as it allows the user to
use a library without having to know the export name.
2.  Default exports allow more streamlined renaming of the imported binding.
3.  Default exports allow smoother interoperability with legacy modules.

The responses to these arguments are:

1.  It's not clear that anonymous APIs add value, since the user of an API
always has to refer to it's documentation, and therefore will always be
exposed to its exported API names.
2.  From experience with other languages like Python, we know that import
renaming is the exception rather than the rule.  As such, streamlined
renaming only results in a marginal benefit.
3.  Interoperability with legacy modules is possible by using a simple
naming convention.  Default exports would improve the user experience of
importing from legacy modules somewhat, but optimizing legacy modules
should not be a primary motivating factor in the design.

And

4.  The default export feature is confusing to users, because it gives the
appearance of module-object-overwriting (in the Node sense) while acting
completely different on a semantic level.  Syntactically, the design favors
default exports while semantically it favors named exports.  Since the
module system is the entry point to the language for users of all
experience levels, the module system should not be confusing.  It should be
as simple and obvious as possible.

Given that the costs (4) do not outweigh the benefits (1, 2, 3), default
exports should be dropped.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-07-01 Thread Kevin Smith
My recommendation is to drop the default export feature and leave
everything else as is (except perhaps for making module.x equivalent to x
per Andreas).  Given that the current module system has far better support
for circular dependencies than module-as-module designs, the static
export design should be retained.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-07-01 Thread Kevin Smith
 My recommendation is to drop the default export feature and leave
 everything else as is (except perhaps for making module.x equivalent to x
 per Andreas).  Given that the current module system has far better support
 for circular dependencies than module-as-module designs, the static
 export design should be retained.


er, module-as-object designs : )
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-07-01 Thread Kevin Smith
 If it had good enough support for circular dependencies, would we be able
 to make sense of module-as-module designs?


Side note:  I meant object-as-module really.  It's kinda funny that I
capped off all of that with such a silly mistype. : )
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-07-01 Thread Calvin Metcalf
one benefit of default exports is forcing people to choose one of

export { x as exports };
export { x as default };
export { x as _ };

this is the one chance to get everyone on the same page


as far as object-as-module having circular dependency issues, can you
elaborate on that, I understand how

let {foo, bar} = import './baz';

would have circular reference problems (amongst other issues), but

module name from './path'
...
name.method();

is (~)what node uses and has comparable (better for certain things, worse
for others) circular dependency support (source: writing a CJS loader using
the es6 loader hooks api) the difficulties I can see with modules as
objects involve static analysis.



On Tue, Jul 1, 2014 at 1:22 PM, Kevin Smith zenpars...@gmail.com wrote:


 If it had good enough support for circular dependencies, would we be able
 to make sense of module-as-module designs?


 Side note:  I meant object-as-module really.  It's kinda funny that I
 capped off all of that with such a silly mistype. : )



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




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


Re: ModuleImport

2014-07-01 Thread C. Scott Ananian
On Tue, Jul 1, 2014 at 1:36 PM, Calvin Metcalf calvin.metc...@gmail.com
wrote:

 one benefit of default exports is forcing people to choose one of

 export { x as exports };
 export { x as default };
 export { x as _ };

 this is the one chance to get everyone on the same page


I think if default exports were dropped, it would certainly be worth an
explicit non-normative mention in the spec text that the export named _ is
reserved for interoperability with legacy module systems or something like
that.  There aren't *that* many widely-used module systems, social pressure
and an explicit recommendation is probably sufficient to get them all on
the same page.  (And presumably the legacy loader implementations which
provide interoperability have a good deal of influence here.)

as far as object-as-module having circular dependency issues, can you
 elaborate on that, I understand how

[...]

 is (~)what node uses and has comparable (better for certain things, worse
 for others) circular dependency support (source: writing a CJS loader using
 the es6 loader hooks api) the difficulties I can see with modules as
 objects involve static analysis.


This is, indeed, worth exploring further.  Node.js has a very
straightforward mechanism for dealing with circular dependencies.  As long
as you make all of your references indirectly through the module object
they are mutable.  This is pretty much exactly equivalent to what ES6
modules provide, with the exception that they save the required
modulename. prefix -- but at the cost of possible user confusion, since
JavaScript has never had mutable bindings in the way that the ES6 module
system provides them.

If we're cutting things from the ES6 module spec, can we consider cutting
the magical mutable `import {foo} from ./foo;` bindings as well?
 Experience has shown that the rare cases where circular dependencies are
intended and used can deal with the overhead of prefixing the module object.

Personally, I would like to introduce mutable bindings as a future
language-level feature, not as some weird wart on the module design.
  --scott
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-07-01 Thread Marius Gundersen
Can't proxies or getters/setters be used to get objects to behave like they
have named exports? As in, when getting a property of the object it looks
up the current value of the bound value in the module. I can't see why this
wouldn't work, but there is probably a reason since nobody has proposed it
yet.

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


Re: ModuleImport

2014-07-01 Thread Kevin Smith
 module name from './path'
 ...
 name.method();


Right - that would work for objects-as-modules, but this wouldn't:

import { something } from ./path;

Unless you somehow emitted getters for all references to something.
 Without consulting documentation, I would expect that these two things:

module x from ./path;
// From within some function or other
x.foo();

import { foo } from ./path;
// From within some function or other
foo();

would be equivalent.  I think a beginner would find a difference there
surprising.

Also, consider hoisting.

// Call an imported function directly
import { foo } from ./path;
foo(123);

module m from ./path;
m.foo();

With object-as-module, neither one is going to work if you have a
circular dependency at play.

Of course, these gains aren't giant - they support edge cases.  But they
are real.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: ModuleImport

2014-07-01 Thread Domenic Denicola
From: es-discuss es-discuss-boun...@mozilla.org on behalf of C. Scott Ananian 
ecmascr...@cscott.net

 If we're cutting things from the ES6 module spec, can we consider cutting the 
 magical mutable `import {foo} from ./foo;` bindings as well?  Experience 
 has shown that the rare cases where circular dependencies are intended and 
 used can deal with the overhead  of prefixing the module object.

Yes, please. Strong +1. As long as we're in the magical land of theorycraft 
where we're dropping features of consensus-modules, and completely off the 
topic of the OP: let's drop mutable bindings, and keep default exports.

Personally, I would like to introduce mutable bindings as a future 
language-level feature, not as some weird wart on the module design.

I would rather never introduce them at all. But I agree with the sentiment that 
having them sneak in through the module syntax backdoor is silly.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-07-01 Thread Kevin Smith
 If it had good enough support for circular dependencies, would we be able
 to make sense of module-as-module designs?


OK, so let's assume for the sake of argument that objects-as-modules is
not confusing, so (4) doesn't apply.  All of the arguments for and against
default exports also apply to module-object-overwriting.  As such, we are
balancing the marginal user experience gains of export-overwriting
against the better support for circular dependencies of real modules.

And we must note that allowing users to overwrite the module-object
eliminates the advantages of statically analyzable exports in those cases.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-07-01 Thread Kevin Smith
 As such, we are balancing the marginal user experience gains of
 export-overwriting against the better support for circular dependencies
 of real modules.


Another way of looking at it:

Being in control of the language, you can always invent new sugar to
optimize user experience (within limits) when real usage data proves its
worth.  But the core model can't be changed.

As such, it seems like it would be better to err on the side of making the
core model simple and solid, leaving minor UX optimizations to future
syntax.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-30 Thread Andreas Rossberg
On 27 June 2014 21:45, C. Scott Ananian ecmascr...@cscott.net wrote:
 On Fri, Jun 27, 2014 at 3:34 PM, Andreas Rossberg rossb...@google.com
 wrote:

 All this means is that there will effectively be two different module
 systems, and in practice, every module provider has to pick one. Which
 is a problem, not a solution.

 ...this is why I've been arguing strongly for consistent syntax regardless.
 Static checking and lazy binding should be value added features, not
 something I have to think about every time I import a module.

Painting over semantic differences by using the same syntax is not an
improvement in usability. It decreases readability, and increases
confusion and surprise. You probably weren't around when this was
discussed last time, but the differences between importing from a
proper module and importing from a singleton export object are not
just in static checking. They create different bindings. The former
creates an _alias_ for the variable from the module. The latter would
need to destructure the property into a _new_ variable, i.e., would
need to _copy_ its state. This leads to visibly different results when
the variable is mutated (internally or externally).

Please assume that all these ideas have been discussed extensively,
and carefully considered, in particular by Dave and Sam. And while I
do not agree with all conclusions, the current design has gotten much
more thought in it than many in this thread seem to assume. In
particular, none of the suggestions made in this thread so far are
new.

  The hybrid, best of both worlds approach you seem to
  have in mind is technically impossible, unfortunately.
 
  I look forward to a technical proof then.  You have not yet provided
  that.

 Well, I don't know how it could be done. I think the proof obligation
 is on those who claim it's possible. ;)

 jslint/jshint is already a (hacky) proof for the most common cases.  It
 detects undeclared variables.  All you need to do is write a loader which
 will prepopulate the jshint's 'predef' field appropriately.

 More complicated sorts of static checking fall to Turing completeness.  Ie:

 ```
 import foo from foo;

 var bat = (Math.random()  1) ? foo : { };

 console.log(bat.baz); // is this a static error?
 ```

 The reasonable thing is to accept incompleteness and provide static checking
 of the common cases: barewords and module name.identifier productions.
 Both of those tests are quite capable of skipping tests if module name is
 not a pure module.

And that is exactly why real ES6 modules are more structured. They
are carefully crafted such that checking of imports/exports is
_always_ possible. And as I said earlier, any attempt to make them
interchangeable with legacy-style modules would break this property.

We can decide that this checking is not worth it and drop it. But we
cannot have our cake and eat it too.

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


Re: ModuleImport

2014-06-30 Thread John Barton
Let me try to restate my request for clear information on the advantages of
module bindings vs module object architectures.

The import syntax already allows pre-execution tools to collect every
module that will be accessed by a root dependent module (including some
that may not be used).  This advantage is clear and it can be weighed
against the disadvantages, including more syntax restrictions to learn and
the need for a separate dynamic API.  On balance I think it's a win,
because I understand the advantage.

What's not clear is the advantage of module bindings form for modules.
 When the world of possibilities opens up, what specific things will I see
there?


On Sun, Jun 29, 2014 at 7:46 PM, Kevin Smith zenpars...@gmail.com wrote:

 Bruno and John's arguments are classic examples of the straw man fallacy.
  In my concrete examples I made no reference to static type systems (or any
 type systems at all, for that matter).  I merely pointed out that by
 allowing the programmer to provide compile-time information in the form of
 exports and declarative forms, a world of possibilities opens up.

 Of course, static information can always be *inferred* from dynamic.
  That's basically how JS engines work, but raising that up to some ideal
 principle is foolish dogmatism.

 They accuse me of advocating decades-old technology, but it is purely
 dynamic JS that is decades old.  Evolve or die is the way.  The we don't
 need no stinkin' classes argument is counter-productive, counter-intuitive
 reactionary garbage, and quite frankly it bores me.

 : P


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


Re: ModuleImport

2014-06-30 Thread Rick Waldron
On Sun, Jun 29, 2014 at 1:00 PM, Domenic Denicola 
dome...@domenicdenicola.com wrote:

 On Jun 29, 2014, at 12:50, Rick Waldron waldron.r...@gmail.com wrote:
  Static analysis would be necessary if JavaScript ever wanted to make
 macros possible in modules. I don't have exact numbers nor have I done any
 formal surveys, but the general response to Sweet.js has been
 overwhelmingly positive. It would be a shame to close that door.

 My understanding is that door is already closed, since we were not able to
 eliminate the global scope contour from modules (which is necessary to get
 completely-static knowledge of all free identifiers). Part of the
 rationalization for this was that compile-time tools (like Sweet.js) are
 working out pretty well.

 See Back to Static Checking in http://esdiscuss.org/notes/2013-09-18


Yes, it appears I forgot about this. Thanks for the follow up.

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


Re: ModuleImport

2014-06-30 Thread C. Scott Ananian
On Mon, Jun 30, 2014 at 7:14 AM, Andreas Rossberg rossb...@google.com
wrote:

  ...this is why I've been arguing strongly for consistent syntax
 regardless.
  Static checking and lazy binding should be value added features, not
  something I have to think about every time I import a module.

 Painting over semantic differences by using the same syntax is not an
 improvement in usability. It decreases readability, and increases
 confusion and surprise. You probably weren't around when this was
 discussed last time, but the differences between importing from a
 proper module and importing from a singleton export object are not
 just in static checking. They create different bindings. The former
 creates an _alias_ for the variable from the module. The latter would
 need to destructure the property into a _new_ variable, i.e., would
 need to _copy_ its state. This leads to visibly different results when
 the variable is mutated (internally or externally).


Yes, I am aware of that.  I also claim that in most module code this
difference is insignificant.  That is, it continues to be best practice to
*avoid* creating circular dependencies in modules.  Further, self-contained
modules will have no need to export lazy-bound references, even if they use
them internally.

I *have* been around for these discussions.  And my conclusion is that the
dogmatists are getting in the way.  Just because there are *some*
differences between modules and objects doesn't mean that *all* users must
be confronted with them.  Just because *some* modules may be defined in a
way to prevents robust checking of modules doesn't mean that *all* modules
must be prevented from doing so.


 Please assume that all these ideas have been discussed extensively,
 and carefully considered, in particular by Dave and Sam. And while I
 do not agree with all conclusions, the current design has gotten much
 more thought in it than many in this thread seem to assume. In
 particular, none of the suggestions made in this thread so far are
 new.


I agree that the discussion has gone in many circles.  But it is also clear
that the consensus is fragile and the compromises not well-liked.  I don't
know of a better way to make continued progress other than (a) proposing
tweaks to the existing compromise that might enhance its appeal, or (b)
continuing to discuss the trade-offs made in an effort to solidify the
consensus.

We can decide that this checking is not worth it and drop it. But we
 cannot have our cake and eat it too.


Concretely I'm proposing that we drop only the must and all phrases
with respect to checking.  I think we can come up with a design where
checking is mostly and usually possible.  This will put the decision in
the hands of the code authors, who can either decide to (a) gradually
transition their legacy code bases to allow more checking, or (b) decide
that the checking is not worth it *for their particular code base*.
  --scott
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-30 Thread Andreas Rossberg
On 30 June 2014 19:01, C. Scott Ananian ecmascr...@cscott.net wrote:
 On Mon, Jun 30, 2014 at 7:14 AM, Andreas Rossberg rossb...@google.com
 wrote:

  ...this is why I've been arguing strongly for consistent syntax
  regardless.
  Static checking and lazy binding should be value added features, not
  something I have to think about every time I import a module.

 Painting over semantic differences by using the same syntax is not an
 improvement in usability. It decreases readability, and increases
 confusion and surprise. You probably weren't around when this was
 discussed last time, but the differences between importing from a
 proper module and importing from a singleton export object are not
 just in static checking. They create different bindings. The former
 creates an _alias_ for the variable from the module. The latter would
 need to destructure the property into a _new_ variable, i.e., would
 need to _copy_ its state. This leads to visibly different results when
 the variable is mutated (internally or externally).

 Yes, I am aware of that.  I also claim that in most module code this
 difference is insignificant.  That is, it continues to be best practice to
 *avoid* creating circular dependencies in modules.  Further, self-contained
 modules will have no need to export lazy-bound references, even if they use
 them internally.

I don't understand what you mean by lazy-bound references. In any
case, the problem exists independent of circular module dependencies.

 I *have* been around for these discussions.  And my conclusion is that the
 dogmatists are getting in the way.  Just because there are *some*
 differences between modules and objects doesn't mean that *all* users must
 be confronted with them.  Just because *some* modules may be defined in a
 way to prevents robust checking of modules doesn't mean that *all* modules
 must be prevented from doing so.

I don't follow this line of reasoning. The language should define
clearly what a module is, what you can expect from it, and it should
do so consistently. Making it fuzzy and unreliable will just bite
everybody, especially since modules will define the boundaries between
code developed by different parties. If that's dogmatic then call me
that.

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


Re: ModuleImport

2014-06-30 Thread Karolis Narkevičius
It's not just about interoperability. It's also about enabling the pattern
that proved itself to work quite well - module as a function, module as a
class, module as a function with named exports attached in one namespace.

I suppose if that pattern is not explicitly supported it might be just fine
since perhaps we'll discover better patterns. And if not, we'll be able to
just always use 1 named export and do

```
import {fs} from fs;
import {moment} from moment;
import {$} from jquery;
// etc.
```

In fact, doesn't being able to import things like above make es6 modules
already interoperable with CJS?


On Mon, Jun 30, 2014 at 8:00 PM, Kevin Smith zenpars...@gmail.com wrote:


 What's not clear is the advantage of module bindings form for modules.
  When the world of possibilities opens up, what specific things will I see
 there?


 I think I'm following you now.  So let's pose the question like this:

 Let's posit that there are no default export or import forms, otherwise
 the current *syntax* is the same.  Now, we have two semantic options that
 we can attach to that syntax:

 1.  Modules are just regular objects with getters.  The import
 declarations just get properties from those objects at runtime.
 2.  Modules are a collection of named bindings.  Those bindings are
 resolved at compile-time.

 Now, since the syntax is the same, our ability to do offline static
 analysis is the same.  So what are the differences between these two
 semantics?

 (All of this has been gone over before, of course...)

 Advantages of 1:

 - None?

 Advantages of 2:

 - Good support for circular dependencies
 - Mutable bindings
 - Compile-time optimizations for module.member expressions

 The advantage of 1 only appears if we allow module object overwriting.
  Those advantages are:

 - Auto-renaming the import (questionable)
 - Smoother interoperability with CommonJS modules.

 On the other hand, module object overwriting disables our ability to do
 offline static analysis.

 So I think the only forceful argument if favor of option 1 (i.e. modules
 are regular objects with getters) is interoperability, and only if we allow
 export overwriting.

 The interoperability question is therefore of central importance.


 ___
 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-30 Thread C. Scott Ananian
On Jun 30, 2014 3:59 PM, Karolis Narkevičius karoli...@gmail.com wrote:
 In fact, doesn't being able to import things like above make es6 modules
already interoperable with CJS?

Almost, but not quite, since the name of the module itself ($, fs, etc) is
not included in a typical commonjs module.  So it would really be:
```
import {_ as $} from jquery;
// etc
```
And from here the jump to default import as a small syntactic improvement
on this seemed clear. (At the time at least.)
  --scott
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-30 Thread Kevin Smith
 It's not just about interoperability. It's also about enabling the pattern
 that proved itself to work quite well - module as a function, module as a
 class, module as a function with named exports attached in one namespace.


But we have to ask why that pattern worked out, and my take is that the
user experience with CJS modules (which exported just a single) was poor.
 ES6 modules don't have that problem.


 I suppose if that pattern is not explicitly supported it might be just
 fine since perhaps we'll discover better patterns.


That's the idea.


 And if not, we'll be able to just always use 1 named export and do

 ```
 import {fs} from fs;
 import {moment} from moment;
 import {$} from jquery;
 // etc.
 ```


Right.


 In fact, doesn't being able to import things like above make es6 modules
 already interoperable with CJS?


(Looks like Scott got here first...)

Mostly.  If you have a Node module which does the overwrite thing then you
might have to assign an arbitrary export name to import it:

import { exports as Emitr } from emitr;

(Where exports is arbitrarily chosen by the module environment.)

But there are other issues which make the interoperability thing more
complicated:  modules have different syntax than scripts, and modules must
be parsed in strict mode.  So you need to know before you load the module,
what kind of module it is (ES6 or CJS).

What we need is a complete interoperability story.  I have some ideas which
I'll write up when I get a chance.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-30 Thread Calvin Metcalf
Another interoperability issue is circular dependencies, es6 modules have
support for certain kinds that cjs doesn't (like function declarations)
and cjs has support for 2 modules using  each others exports (as long as
they arn't single exports).

If it wasn't for this you could load cjs modules with just normalize and
translate hooks. At the moment you can likely get around the difference
with an instantiate hook, but I haven't had time to check yet.
On Jun 30, 2014 4:11 PM, Kevin Smith zenpars...@gmail.com wrote:


 It's not just about interoperability. It's also about enabling the pattern
 that proved itself to work quite well - module as a function, module as a
 class, module as a function with named exports attached in one namespace.


 But we have to ask why that pattern worked out, and my take is that the
 user experience with CJS modules (which exported just a single) was poor.
  ES6 modules don't have that problem.


 I suppose if that pattern is not explicitly supported it might be just
 fine since perhaps we'll discover better patterns.


 That's the idea.


 And if not, we'll be able to just always use 1 named export and do

 ```
 import {fs} from fs;
 import {moment} from moment;
 import {$} from jquery;
 // etc.
 ```


 Right.


 In fact, doesn't being able to import things like above make es6 modules
 already interoperable with CJS?


 (Looks like Scott got here first...)

 Mostly.  If you have a Node module which does the overwrite thing then you
 might have to assign an arbitrary export name to import it:

 import { exports as Emitr } from emitr;

 (Where exports is arbitrarily chosen by the module environment.)

 But there are other issues which make the interoperability thing more
 complicated:  modules have different syntax than scripts, and modules must
 be parsed in strict mode.  So you need to know before you load the module,
 what kind of module it is (ES6 or CJS).

 What we need is a complete interoperability story.  I have some ideas
 which I'll write up when I get a chance.

 ___
 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-30 Thread John Barton
On Mon, Jun 30, 2014 at 12:00 PM, Kevin Smith zenpars...@gmail.com wrote:


 What's not clear is the advantage of module bindings form for modules.
  When the world of possibilities opens up, what specific things will I see
 there?


 I think I'm following you now.  So let's pose the question like this:

 Let's posit that there are no default export or import forms, otherwise
 the current *syntax* is the same.  Now, we have two semantic options that
 we can attach to that syntax:

 1.  Modules are just regular objects with getters.  The import
 declarations just get properties from those objects at runtime.
 2.  Modules are a collection of named bindings.  Those bindings are
 resolved at compile-time.

 Now, since the syntax is the same, our ability to do offline static
 analysis is the same.  So what are the differences between these two
 semantics?


Thanks! This is the kind of information I was hoping for.



 (All of this has been gone over before, of course...)


Perhaps, but clear explanation of complex topics is difficult.  Isolating
the issues and getting to specifics helps. In that spirit I'll ask for more
details.



 Advantages of 1:

 - None?

 Advantages of 2:

 - Good support for circular dependencies
 - Mutable bindings


As far as I know, this is not something JS developers understand. What is
it and what makes it an advantage?


 - Compile-time optimizations for module.member expressions


Is this known to be significant and fundamental? As in there is no way to
achieve this optimization with the other format? Seems to me that the
compiler introduces the getters and thus can inline them.


 The advantage of 1 only appears if we allow module object overwriting.


Concretely you mean monkey patching module objects in the importing code?
Or?


 Those advantages are:

 - Auto-renaming the import (questionable)
 - Smoother interoperability with CommonJS modules.

 On the other hand, module object overwriting disables our ability to do
 offline static analysis.

 So I think the only forceful argument if favor of option 1 (i.e. modules
 are regular objects with getters) is interoperability, and only if we allow
 export overwriting.

 The interoperability question is therefore of central importance.


Based on other discussion on this point, it seems like
module-as-named-bindings can interoperate with CJS and AMD except perhaps
in some unusual cases. Clarifying these cases would help.

To me, these two lists are pretty darn small compared with the overall
advantages of modules.

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


Re: ModuleImport

2014-06-30 Thread C. Scott Ananian
On Mon, Jun 30, 2014 at 4:32 PM, John Barton johnjbar...@google.com wrote:

 Based on other discussion on this point, it seems like
 module-as-named-bindings can interoperate with CJS and AMD except perhaps
 in some unusual cases. Clarifying these cases would help.

 To me, these two lists are pretty darn small compared with the overall
 advantages of modules.


Note that, although this particular thread has gotten hung up on default
import/export, mutable bindings, and export, there are some other
significant incompatibilities.  Bundling is one such example.  Integration
with HTML fetch is another.  I defer to @jrburke, @domenic, and @hixie for
the details.
  --scott
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-30 Thread Kevin Smith


 - Mutable bindings


 As far as I know, this is not something JS developers understand. What is
 it and what makes it an advantage?


Since imported bindings are just aliases for variables over in the
originating module, changing the value of that variable in the exporting
module will change value of the corresponding binding on the import side.

This is important for circular dependencies, because an imported binding
needs to get updated when the initialization phase runs to completion.

Outside of circular dependencies, I don't know.  I'm sure someone can find
a good use case for it : )



 - Compile-time optimizations for module.member expressions


 Is this known to be significant and fundamental? As in there is no way to
 achieve this optimization with the other format? Seems to me that the
 compiler introduces the getters and thus can inline them.


If there is no module object overwriting, then I suppose it could be
inlined.  If you allow overwriting, then you would need the further
restriction that you cannot import from overridden module objects.




 The advantage of 1 only appears if we allow module object overwriting.


 Concretely you mean monkey patching module objects in the importing code?
 Or?


I mean something equivalent to `module.exports = whatever`, where the
object stored in the registry was replaced by some arbitrary,
user-specified object.



 The interoperability question is therefore of central importance.


 Based on other discussion on this point, it seems like
 module-as-named-bindings can interoperate with CJS and AMD except perhaps
 in some unusual cases. Clarifying these cases would help.


As Scott and I pointed out, unless you have module-object overwriting (or
default exports), then you have to use some arbitrary name for CJS modules
that use the `module.exports = x` idiom.  And that's the only real
advantage of the module-as-object semantics.  In fact, it doesn't really
fly without it.



 To me, these two lists are pretty darn small compared with the overall
 advantages of modules.


So we should just pick a core semantics and get on with it?  I agree, but
we have to decide whether module-object-overwriting is a design requirement
or not.

To sum up, the strongest advantages are:

Option 1A (modules are regular objects which can be overwritten):  Possibly
better interoperability with CJS modules

Option 2 (modules as named remote bindings): Better support for circular
dependencies
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-30 Thread Kevin Smith


 If there is no module object overwriting, then I suppose it could be
 inlined.  If you allow overwriting, then you would need the further
 restriction that you cannot import from overridden module objects.


Sorry, strike the second sentence.  (Trying to do too many things at once!)
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-29 Thread Isiah Meadows
I think that a possible compromise that can still make the ES6 module
system more compatible with both AMD and CommonJS modules is by this:

If there are no exports from a module, named or not, make the export
process implementation-defined. If an ES5 Node module uses module.exports,
then Node could configure the exports to be importable through the ES6
syntax. Some people use named exports, while others have even exported a
constructor via module.exports. In the browser environment, it could be
something along the lines of using the added Window properties as named
exports.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-29 Thread John Barton
Thanks Kevin. I'm going to challenge your list below, but I hope you don't
take it negatively.  I want the case for the module system to be as strong
as possible.


On Sat, Jun 28, 2014 at 11:51 AM, Kevin Smith zenpars...@gmail.com wrote:


 Static checking of imports and exports has well-known advantages and
 would help the long-term viability of the language.


 Enumerating these specific advantages would inform this discussion.
  These advantages are not well-known. Many developers have experienced the
 disadvantages of complex systems of rules and thus favor simple solutions
 over ones with theoretical advantages. Explaining the benefits concretely
 would help them balance the well-known costs.


 So pretty much everything in Javascript is dynamic, which is one reason
 why IDE support for Javascript has always lagged behind.  You simply can't
 know what anything is until you actually run the program.  Statically
 verifiable exports gives us the ability to inspect and analyze code without
 having to run it.  There are two big benefits that this affords us:

 ## Early Errors and Warnings ##

 Let's say that you want to deprecate and remove an exported member from a
 module within a large JS code base.  With static imports, the system will
 generate an error at compile time if something on the other side of that
 codebase is importing it.


It seems to me that the compiler can verify these two statements with equal
success:
  import {foo} from './foo';
  var foo = require('./foo.js').foo;
I agree that as a practical matter compilers may be more likely to
implement checks on the first form simply because it is standard.  And I
agree that the language-defined module syntax will lead to better quality
tools simply because more developers have formal training in compiler
technology than have training in dynamic analysis.  These are important
pragmatic issues.

Or am I wrong and these are not equivalent? Or there are examples which
show the issue more clearly?


 For exported function declarations that use default parameters to indicate
 optional parameters, we can generate build-time warnings when such an
 function is imported and called with too few arguments.


A good argument for default parameters.



 For exported classes, we have even more static information at our hands.
  Without having to run the program, we know the number of arguments for the
 constructor and we know the list of methods for class instances.  We can
 generate warnings when we see an instance using a misspelled method name,
 for instance.


A good argument for standard rather than ad-hoc class class syntax.



 ## Computer Aided Coding ##

 The information used above to generate lint-like warnings can also be used
 to give the developer in-editor feedback.  Reliable code-completion for
 imported function and class declarations becomes possible.  Again, for
 exported classes we can also do code completion for instance methods.

 These advantages may not seem like a big deal now, but imagine writing JS
 in a large team five years from now.  Do you want the power of static
 analysis at your team's fingertips, or do you want to be stuck with
 anything goes so anything can break CommonJS modules?

 Does that do it?


These are arguments for statically computable import module names -- so the
compiler can determine the imports without executing source code -- and for
top-level or hoisted (static) import statements -- so every import in a
module is a dependency of the module without runtime conditionals. I
believe that both of these limitations would be acceptable to almost all
developers interested in using modules.

Unfortunately I think we need more specific and detailed examples to
understand the advantages of the static form.
Thanks,
jjb
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-29 Thread John Barton
On Sat, Jun 28, 2014 at 3:58 PM, Kevin Smith zenpars...@gmail.com wrote:

 Static checking will be limited anyway. If you want to go this way you
 should use typescript.


 That's the point that I'm trying to make, shops will choose other
 languages that provide more static information.  We should be thinking
 about expanding the user base and ensuring that JS is a viable option years
 down the road.


JavaScript's enormous user base is the strongest possible evidence that
static analysis provides no advantage to programming language viability.
Static analysis may encourage some new users; overall complexity may
discourage as many.  (I recently started using a typed version of JS;  I am
not impressed.)

Any survey of the top languages in actual use clear demonstrates that the
runtime platform and app goals dominate language choice. Even within a
platform it is clear static checks are way down the list of valued
features.

Rather than point towards type-checking, I think we should focus on the
actual checks offered by the module design. It seems that these would come
with a small cost quite unlike type-checking.



 CommonJS falls a bit short on the import side because static analysis of
 require calls is brittle. A special language syntax would enable a robust
 static analysis of dependencies.


 If you don't have static exports, then how are you going to know if what
 you import is valid?  You can't, without executing the program.


If you don't execute the program, how do you know if the code you are
checking is even called? Oh, you do plan to execute the program. Well there
you go.

(I just think it is so weird that JavaScript's huge advantage of rapid
dynamic feedback for developers receives so little attention while so much
is lavished on static technologies developed decades ago for a computing
environment vastly inferior to our current world.)

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


Re: ModuleImport

2014-06-29 Thread Domenic Denicola
On Jun 29, 2014, at 12:50, Rick Waldron waldron.r...@gmail.com wrote:
 Static analysis would be necessary if JavaScript ever wanted to make macros 
 possible in modules. I don't have exact numbers nor have I done any formal 
 surveys, but the general response to Sweet.js has been overwhelmingly 
 positive. It would be a shame to close that door. 

My understanding is that door is already closed, since we were not able to 
eliminate the global scope contour from modules (which is necessary to get 
completely-static knowledge of all free identifiers). Part of the 
rationalization for this was that compile-time tools (like Sweet.js) are 
working out pretty well.

See Back to Static Checking in http://esdiscuss.org/notes/2013-09-18
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-29 Thread Bruno Jouhier
 CommonJS falls a bit short on the import side because static analysis of
 require calls is brittle. A special language syntax would enable a robust
 static analysis of dependencies.


 If you don't have static exports, then how are you going to know if what
 you import is valid?  You can't, without executing the program.


The main purpose of modules is not to provide static type checking but to
prevent global scope pollution and allow loaders to load source code
reliably and efficiently. What I meant by static analysis was the ability
for a loader to bundle all the dependencies so that they can be transported
efficiently. With require this analysis is brittle because require is not a
reserved keyword and its argument can be any expression.

It is important to focus the design on loader issues and keep things
orthogonal.

Why reinvent a special destructuring syntax when this is already addressed
by existing language constructs? It can be handled by allowing any LHS
after the as keyword: import module_path as lhs_expression;

Why bother about about static type checking? If you want static typing, use
Typescript, your modules will be exporting typed APIs; if you don't care
use JavaScript.

Sorry for the previous empty post. I hit the wrong key.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Re: ModuleImport

2014-06-29 Thread Brian Di Palma
 Static checking will be limited anyway. If you want to go this way you shoud 
 use typescript.

If you don't want static checking you should stick with ES3. Fixed that for you.

Yes big projects are possible with JS, I work on them everyday. It
would be nice if the language made them easier, that's what we are
talking about.
Big projects are possible with C, why bother with any other language?
With sufficient rigor Assembly will do the trick. Just have good code
reviews and test.

 ability to dynamically import modules in addition to static imports. IMO this 
 should be packaged as an async API

I think this is already possible using the loader.

 hooks for transpilers. This should also be an API

Ditto.

 Usually, I obtain the same benefit running the tests (and more, test that 
 were the product of TDD workflow)

I can forsee many people writing tests where they configure the module
loader to load mocks instead of true dependencies.
This could result in tests passing while there is a breakage in the application.

If the language can make some of these problems go away then we are better off.
It's just like tests, code review and linting, it's another type of
verification.

 I think that a possible compromise that can still make the ES6 module system 
 more compatible with both AMD and CommonJS modules

The ES6 module system is compatible with CommonJS and AMD, I'm happily
mixing the two together with libraries like SystemJS

https://github.com/systemjs/systemjs/

For example

https://github.com/briandipalma/flux-es6/blob/master/src/Store.js

The Emitr class here is imported from a CommonJS module

 It is important to focus the design on loader issues and keep things 
 orthogonal.

The Loader is quite solid and well designed, I've not heard any major
issues with it. What does it have to do with this discussion?

 import {foo} from './foo';
 var foo = require('./foo.js').foo;

I though those two statements weren't comparable?
The import statement can only be present at the module top level while
the require can be written in any code block.
That leaves it open to the random number require issues which makes
static checking impossible.
As you pointed out it's not a language standard so I'd imagine that's
another reason why tooling is so weak.

 Rather than point towards type-checking, I think we should focus on the 
 actual checks offered by the module design.
 It seems that these would come with a small cost quite unlike type-checking.

Unless I'm misunderstanding Kevin I think we've both talking about
exactly that. I guess people saw static and automatically added
type.
Just static checking of import and export bindings. A much smaller
scope feature then static type checking.

This discussion has veered off track, it's about a new ModuleImport
form, which grew into questioning if default imports/exports was the
real problem.
I'd be interested in knowing if it's possible that instead of changing
the ModuleImport form the default import/export idea could be
postponed instead.

It could be added in later if there really was need for it.
As far as I can tell libraries like SystemJS can smooth over issues
caused by importing from legacy module systems like CommonJS and AMD.
Leaving default imports/exports an odd third way to import that was
added based on some notion of backward compatability that wasn't
needed.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-29 Thread Kevin Smith
Bruno and John's arguments are classic examples of the straw man fallacy.
 In my concrete examples I made no reference to static type systems (or any
type systems at all, for that matter).  I merely pointed out that by
allowing the programmer to provide compile-time information in the form of
exports and declarative forms, a world of possibilities opens up.

Of course, static information can always be *inferred* from dynamic.
 That's basically how JS engines work, but raising that up to some ideal
principle is foolish dogmatism.

They accuse me of advocating decades-old technology, but it is purely
dynamic JS that is decades old.  Evolve or die is the way.  The we don't
need no stinkin' classes argument is counter-productive, counter-intuitive
reactionary garbage, and quite frankly it bores me.

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


Re: Re: ModuleImport

2014-06-29 Thread Kevin Smith


 I'd be interested in knowing if it's possible that instead of changing
 the ModuleImport form the default import/export idea could be
 postponed instead.


It can.  Just to be clear, that means that we'd have these two forms on the
import side:

module FS from fs;
import { stat } from fs;

which would be cool with me.

I think, though, that the default thing has syntactically been raised up to
an architectural level, and that's the core problem that Andreas has
pointed out.  Once you make the architectural decision to drop it, then
you'll probably never want it.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-28 Thread Isiah Meadows
(I get the digest...)

First, I will say that you all beat me to my (almost) exact suggestion on
the syntax, @Russell and @Scott.

Second, `module foo from 'foo'` is counterintuitive, confusing,
non-obvious, and really needs trashed IMHO.

Now, to supplement these ideas, I will summarize how I think it may work
best:

// import default export(s)

import 'lo-dash' as _;
import 'fs' as fs;

// import specific named export
// imports as $.extend

import extend in $ from 'jquery';

// import multiple named exports
// imports as _, with members .map and .each

import map, each in _ from 'underscore';

// import members of an export
// imports those members into the module namespace

import map, each from 'underscore';

// import all named exports as properties of _
import * in _ from 'lo-dash';

// import all named exports into module namespace

import * from 'lo-dash';

// import as different name in current module

import reallyReallyLongFunctionName as foo from './foo';

// import as different property name
// likely atypical, would show up as something most wouldn't think
// of a while down the road

import reallyReallyLongFunctionName as func in foo from './foo';

The keyword in is used to both note that they are properties in the
module. It is not as to limit confusion: as is better to dictate names.
The basic syntax grammar could be defined as follows (please pardon my
inability to format...I'm typing this from a phone):

ModuleName:
module-path

ModuleName:
'module-path'

ImportStatement:
One of:
DefaultImportStatement
NamedImportStatement

DefaultImportStatement:
import ModuleName as Identifier;

NamedImportStatement:
import NamedImports from ModuleName;

NamedImports:
One of:
NamedIdentifiers
NamedImport

NamedImport:
NamedIdentifiers in Identifier

NamedIdentifiers:
NamedIdentifier , NamedIdentifiers

NamedIdenifiers:
NamedIdentifier

NamedIdentifier:
One of:
Identifier
Identifier as Identifier

This is my proposed syntax. It is somewhat Pythonic, but slightly more
verbose because file names aren't themselves restricted like identifiers.

Here's a couple more real world examples:

import 'jquery' as $;
$('#button').attr('onClick', () = alert('You clicked the button!'));

// == //

import readdir, stat from 'fs';
import 'path' as path;

function walk(dir, cb) {
  readdir(path.resolve(dir), (error, files) = files.forEach(file = {
let file = dir + path.sep + file;
let fileStat = stat(file);
if (fileStat  fileStat.isDirectory()) {
  walk(file, cb);
} else {
  cb(file);
}
  }));
}

Here's the version more popular out of the other suggestions:

import {$} from 'jquery';
$('#button').attr('onClick', () = alert('You clicked the button!'));

// == //

import {readdir, stat} from 'fs';
import path from 'path';

function walk(dir, cb) {
  readdir(path.resolve(dir), (error, files) = files.forEach(file = {
let file = dir + path.sep + file;
let fileStat = stat(file);
if (fileStat  fileStat.isDirectory()) {
  walk(file, cb);
} else {
  cb(file);
}
  }));

Which looks better? Which is more obvious and intuitive?

On another note, look at the bright side and compare these with the ES5
equivalents:

define(['jquery'], function ($) {
  $('#button').attr('onClick', function () {
alert('You clicked the button!');
  });
});

// == //

var fs = require('fs');
var path = require('path');

function walk(dir, cb) {
  fs.readdir(path.resolve(dir), function (error, files) {
files.forEach(function (file) {
  var file = dir + path.sep + file;
  var stat = fs.stat(file);
  if (stat  stat.isDirectory()) {
walk(file, cb);
  } else {
cb(file);
  }
});
  });
}

I think we've made some relatively good progress so far. That last is just
unnecessarily complicated in syntax.

aside
Is it me, or is ECMAScript starting to become Python crossed with a
curly-brace version of Scheme? I'm starting to see a lot of new
functionally oriented syntax and methods being added to ES6 and considered
for ES7, while at the same time Pythonic OOP and reflection being
considered simultaneously. The arrow functions are effectively lambdas that
can be complete functions in their own right.

I wonder how long it will take for people will find out the ease of
currying and more availability of functional techniques in ES6.
var foo = (a, b) = (c) = a * b + c;
var adder = a = b = a + b;
var addOne = adder(1);
var two = addOne(1);
/aside

 -- Forwarded message --
 From: Russell Leggett russell.legg...@gmail.com
 To: Kevin Smith zenpars...@gmail.com
 Cc: es-discuss es-discuss@mozilla.org
 Date: Thu, 26 Jun 2014 10:50:20 -0400
 Subject: Re: ModuleImport

 Now the author can choose to export more things later without making
breaking changes to the module. The only downside

Re: ModuleImport

2014-06-28 Thread Isiah Meadows
I fully admit that I'm probably hanging a little behind in terms of emails
because I get them bundled into 4-5 each.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-28 Thread Bruno Jouhier
Why make things so complex and introduce so many syntax variations? The
following should be sufficient:

import underscore as _; // var _ = require('underscore');

And there should be an API (not a language construct) to import a module
dynamically (and asynchronously). Something like:

promise = importModule(path);

Why introduce an export syntax? Why not just use this (or exports)?

this.foo = ... // or exports.foo = ...
this =  // or exports = ..., similar to module.exports = ...
// importer obtains value of this / exports at end of module file,
// as if `return this` was added at the end of the file.

This would give the same power / flexibility as CommonJS and a simple
compatibility path. This would eliminate the default exports problem
because it would allow a module to export a function. It is also easy to
explain.

There is an operational requirement to have a special syntax for import
because this is what allows loaders to build a dependency graph and
optimize dependency loading. But there is no operational requirement to
have a special syntax for export. Static checking on exported members feels
odd.

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


Re: ModuleImport

2014-06-28 Thread Kevin Smith


 This would give the same power / flexibility as CommonJS and a simple
 compatibility path. This would eliminate the default exports problem
 because it would allow a module to export a function. It is also easy to
 explain.


So this is basically the sugar over CommonJS modules solution.  But why
bother?  require already does all of this and there already exist tools
to generate dependency graphs from require.  No syntax is required.



 Static checking on exported members feels odd.


Static checking of imports and exports has well-known advantages and would
help the long-term viability of the language.  Segments that want static
checking to be a part of their workflow might very well just leave JS for
some other language that provides it.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-28 Thread John Barton
On Sat, Jun 28, 2014 at 9:03 AM, Kevin Smith zenpars...@gmail.com wrote:


 Static checking on exported members feels odd.


 Static checking of imports and exports has well-known advantages and would
 help the long-term viability of the language.


Enumerating these specific advantages would inform this discussion.  These
advantages are not well-known. Many developers have experienced the
disadvantages of complex systems of rules and thus favor simple solutions
over ones with theoretical advantages. Explaining the benefits concretely
would help them balance the well-known costs.

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


Re: ModuleImport

2014-06-28 Thread Matthew Robb
What if the Loader spec had some attention given to match AMD/CommonJS for
some cases and leave the new syntax for the new module semantics. Really
what we want is for non-es6 module systems to be able to hook into the
loader registry in a way that makes sense for them and will also make sense
for IMPORTING those modules into es6 modules. require/define work in
browsers and in node TODAY, the conversation imo shouldn't be about giving
those systems better syntax it should be about creating a single
registry/loader that easily supports all paths.


- Matthew Robb


On Sat, Jun 28, 2014 at 9:48 AM, John Barton johnjbar...@google.com wrote:




 On Sat, Jun 28, 2014 at 9:03 AM, Kevin Smith zenpars...@gmail.com wrote:


 Static checking on exported members feels odd.


 Static checking of imports and exports has well-known advantages and
 would help the long-term viability of the language.


  Enumerating these specific advantages would inform this discussion.
  These advantages are not well-known. Many developers have experienced the
 disadvantages of complex systems of rules and thus favor simple solutions
 over ones with theoretical advantages. Explaining the benefits concretely
 would help them balance the well-known costs.

 jjb

 ___
 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-28 Thread Kevin Smith


 Static checking of imports and exports has well-known advantages and
 would help the long-term viability of the language.


 Enumerating these specific advantages would inform this discussion.  These
 advantages are not well-known. Many developers have experienced the
 disadvantages of complex systems of rules and thus favor simple solutions
 over ones with theoretical advantages. Explaining the benefits concretely
 would help them balance the well-known costs.


So pretty much everything in Javascript is dynamic, which is one reason why
IDE support for Javascript has always lagged behind.  You simply can't know
what anything is until you actually run the program.  Statically verifiable
exports gives us the ability to inspect and analyze code without having to
run it.  There are two big benefits that this affords us:

## Early Errors and Warnings ##

Let's say that you want to deprecate and remove an exported member from a
module within a large JS code base.  With static imports, the system will
generate an error at compile time if something on the other side of that
codebase is importing it.

For exported function declarations that use default parameters to indicate
optional parameters, we can generate build-time warnings when such an
function is imported and called with too few arguments.

For exported classes, we have even more static information at our hands.
 Without having to run the program, we know the number of arguments for the
constructor and we know the list of methods for class instances.  We can
generate warnings when we see an instance using a misspelled method name,
for instance.

## Computer Aided Coding ##

The information used above to generate lint-like warnings can also be used
to give the developer in-editor feedback.  Reliable code-completion for
imported function and class declarations becomes possible.  Again, for
exported classes we can also do code completion for instance methods.

These advantages may not seem like a big deal now, but imagine writing JS
in a large team five years from now.  Do you want the power of static
analysis at your team's fingertips, or do you want to be stuck with
anything goes so anything can break CommonJS modules?

Does that do it?
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-28 Thread Bruno Jouhier
Static checking will be limited anyway. If you want to go this way you shoud 
use typescript. 

Big projects are perfectly manageable with CommonJS from my experience with a 
20+ team. The trick is to enforce code reviews and unit tests.

CommonJS falls a bit short on the import side because static analysis of 
require calls is brittle. A special language syntax would enable a robust 
static analysis of dependencies. 

But the export side of CommonJS is basically ok. JS APIs are dynamic and there 
is little value in introducing a shallow and leaky static API verification at 
the module interface.

Two things should not be overlooked in the design:

* ability to dynamically import modules in addition to static imports. IMO this 
should be packaged as an async API

* hooks for transpilers. This should also be an API

Bruno

 Le 28 juin 2014 à 14:51, Kevin Smith zenpars...@gmail.com a écrit :
 
 
 Static checking of imports and exports has well-known advantages and would 
 help the long-term viability of the language.  
 
 Enumerating these specific advantages would inform this discussion.  These 
 advantages are not well-known. Many developers have experienced the 
 disadvantages of complex systems of rules and thus favor simple solutions 
 over ones with theoretical advantages. Explaining the benefits concretely 
 would help them balance the well-known costs.
 
 So pretty much everything in Javascript is dynamic, which is one reason why 
 IDE support for Javascript has always lagged behind.  You simply can't know 
 what anything is until you actually run the program.  Statically verifiable 
 exports gives us the ability to inspect and analyze code without having to 
 run it.  There are two big benefits that this affords us:
 
 ## Early Errors and Warnings ##
 
 Let's say that you want to deprecate and remove an exported member from a 
 module within a large JS code base.  With static imports, the system will 
 generate an error at compile time if something on the other side of that 
 codebase is importing it.
 
 For exported function declarations that use default parameters to indicate 
 optional parameters, we can generate build-time warnings when such an 
 function is imported and called with too few arguments.
 
 For exported classes, we have even more static information at our hands.  
 Without having to run the program, we know the number of arguments for the 
 constructor and we know the list of methods for class instances.  We can 
 generate warnings when we see an instance using a misspelled method name, for 
 instance.
 
 ## Computer Aided Coding ##
 
 The information used above to generate lint-like warnings can also be used to 
 give the developer in-editor feedback.  Reliable code-completion for imported 
 function and class declarations becomes possible.  Again, for exported 
 classes we can also do code completion for instance methods.
 
 These advantages may not seem like a big deal now, but imagine writing JS in 
 a large team five years from now.  Do you want the power of static analysis 
 at your team's fingertips, or do you want to be stuck with anything goes so 
 anything can break CommonJS modules?
 
 Does that do it?
 
 
 
 
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-28 Thread Angel Java Lopez
Maybe, I cannot see all the landscape, but a minor comment, in my limited
English

Related to:
## Early Errors and Warnings ##

Usually, I obtain the same benefit running the tests (and more, test that
were the product of TDD workflow). In this way, I'm sure not only of no
removal of something I needed, but also the underlying behavior of imported
modules are still the same. Relaying on static imports only warns me about
the presence or not of some functions, but the app could be broken

Angel Java Lopez
@ajlopez



On Sat, Jun 28, 2014 at 7:42 PM, Bruno Jouhier bjouh...@gmail.com wrote:

 Static checking will be limited anyway. If you want to go this way you
 shoud use typescript.

 Big projects are perfectly manageable with CommonJS from my experience
 with a 20+ team. The trick is to enforce code reviews and unit tests.

 CommonJS falls a bit short on the import side because static analysis of
 require calls is brittle. A special language syntax would enable a robust
 static analysis of dependencies.

 But the export side of CommonJS is basically ok. JS APIs are dynamic and
 there is little value in introducing a shallow and leaky static API
 verification at the module interface.

 Two things should not be overlooked in the design:

 * ability to dynamically import modules in addition to static imports. IMO
 this should be packaged as an async API

 * hooks for transpilers. This should also be an API

 Bruno

 Le 28 juin 2014 à 14:51, Kevin Smith zenpars...@gmail.com a écrit :


 Static checking of imports and exports has well-known advantages and
 would help the long-term viability of the language.


 Enumerating these specific advantages would inform this discussion.
  These advantages are not well-known. Many developers have experienced the
 disadvantages of complex systems of rules and thus favor simple solutions
 over ones with theoretical advantages. Explaining the benefits concretely
 would help them balance the well-known costs.


 So pretty much everything in Javascript is dynamic, which is one reason
 why IDE support for Javascript has always lagged behind.  You simply can't
 know what anything is until you actually run the program.  Statically
 verifiable exports gives us the ability to inspect and analyze code without
 having to run it.  There are two big benefits that this affords us:

 ## Early Errors and Warnings ##

 Let's say that you want to deprecate and remove an exported member from a
 module within a large JS code base.  With static imports, the system will
 generate an error at compile time if something on the other side of that
 codebase is importing it.

 For exported function declarations that use default parameters to indicate
 optional parameters, we can generate build-time warnings when such an
 function is imported and called with too few arguments.

 For exported classes, we have even more static information at our hands.
  Without having to run the program, we know the number of arguments for the
 constructor and we know the list of methods for class instances.  We can
 generate warnings when we see an instance using a misspelled method name,
 for instance.

 ## Computer Aided Coding ##

 The information used above to generate lint-like warnings can also be used
 to give the developer in-editor feedback.  Reliable code-completion for
 imported function and class declarations becomes possible.  Again, for
 exported classes we can also do code completion for instance methods.

 These advantages may not seem like a big deal now, but imagine writing JS
 in a large team five years from now.  Do you want the power of static
 analysis at your team's fingertips, or do you want to be stuck with
 anything goes so anything can break CommonJS modules?

 Does that do it?





 ___
 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-28 Thread Kevin Smith

 Static checking will be limited anyway. If you want to go this way you
 should use typescript.


That's the point that I'm trying to make, shops will choose other languages
that provide more static information.  We should be thinking about
expanding the user base and ensuring that JS is a viable option years down
the road.


 CommonJS falls a bit short on the import side because static analysis of
 require calls is brittle. A special language syntax would enable a robust
 static analysis of dependencies.


If you don't have static exports, then how are you going to know if what
you import is valid?  You can't, without executing the program.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-28 Thread Kevin Smith


 Usually, I obtain the same benefit running the tests (and more, test that
 were the product of TDD workflow). In this way, I'm sure not only of no
 removal of something I needed, but also the underlying behavior of imported
 modules are still the same. Relaying on static imports only warns me about
 the presence or not of some functions, but the app could be


Of course, there's no substitute for unit tests with good coverage.  But
the question is, what kind of help does that language provide for static
analysis?  Currently, JS provides almost none.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-27 Thread Michał Gołębiowski
On Thu, Jun 26, 2014 at 4:50 PM, Russell Leggett russell.legg...@gmail.com
wrote:


 //import a single named export
 import foo from bar;

 //import multiple named exports
 import foo, baz from bar;

 //alias an imported named export
 import foo as fooAlias from bar;

 //import the module
 import bar as bar;


That would put a lot of Node modules exporting a single object/function at
a disadvantage. Compare:
```js
var mkdr = require('mkdirp');
```
to:
```js
import mkdirp as mkdr from mkdirp;
```

I like that the most common module usage can be done simpler.

-- 
Michał Gołębiowski
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-27 Thread Russell Leggett
On Fri, Jun 27, 2014 at 3:41 AM, Michał Gołębiowski m.go...@gmail.com
wrote:

 On Thu, Jun 26, 2014 at 4:50 PM, Russell Leggett 
 russell.legg...@gmail.com wrote:


 //import a single named export
 import foo from bar;

 //import multiple named exports
 import foo, baz from bar;

 //alias an imported named export
 import foo as fooAlias from bar;

 //import the module
 import bar as bar;


 That would put a lot of Node modules exporting a single object/function at
 a disadvantage. Compare:
 ```js
 var mkdr = require('mkdirp');
 ```
 to:
 ```js
 import mkdirp as mkdr from mkdirp;
 ```

 I like that the most common module usage can be done simpler.


No, that example would be:

import mkdirp as mkdir;

Its actually shorter than node.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-27 Thread Michał Gołębiowski
On Thu, Jun 19, 2014 at 4:04 PM, David Herman dher...@mozilla.com wrote:

 On Jun 19, 2014, at 3:31 AM, Michał Gołębiowski m.go...@gmail.com wrote:

  Compare these 3 forms of importing all the module lodash bindings to
 an object _:
  ```js
  var _ = require(lodash); // Node
  import * as _ from lodash; // Dave's syntax
  import lodash as _;
  ```

 My feeling is that the clutter is small, and it's acceptable to have it be
 slightly less minimal than default export since that is the case we are
 favoring. This isn't so cluttered as to be downright *punishing*
 multi-export utility modules (it's literally only two characters longer
 than your Node code, albeit admittedly a little chattier), but it's good
 that default import is the winner.


IMO it's not even that much a question of taken space but of potential
confusion. People will think if they can do:
```js
import * as _ from lodash;
```
they can do:
```js
import * from lodash;
```
as well. Also, there are reports of thinking that the first form exports
not only the _ container object but also all individual methods as in
Python.

I'd still prefer:
```js
import lodash as _;
```
I think it's less confusing that other proposals and reads naturally; it
also corresponds more to other module systems. But if that's out of the
picture, sth like:
```js
import module _ from lodash;
```
would be IMO less confusing that the proposed `* as _` form.

-- 
Michał Gołębiowski
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-27 Thread Michał Gołębiowski
On Fri, Jun 27, 2014 at 9:44 AM, Russell Leggett russell.legg...@gmail.com
wrote:

 No, that example would be:

 import mkdirp as mkdir;

 Its actually shorter than node.


But in current proposal the module object cannot be a function from what I
understand. So you'd have to create a named export and import it as I wrote.

-- 
Michał Gołębiowski
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-27 Thread Andreas Rossberg
Some observations:

* I think the 'import * as x' syntax for module imports is not an
improvement, for at least two reasons:

  - It raises the expectation that you can actually write 'import *
from' (as already noted in this thread).

  - It removes the syntactic marker for binding a module identifier.
That is problematic because (a) module identifiers come with extra
static checks on their uses (or so I thought, see below), and it is
(b) future hostile to lexical module declarations, because with those,
only module identifiers could be used in certain contexts (e.g., on
the RHS of an import-from). Thinking forward, I think it would be
highly preferable to consistently mark all bindings of module
identifiers with a 'module' keyword.

* I think the controversy is because the module design tries pleasing
two incompatible community goals, but instead of achieving that, it
has acquired all the characteristics of a committee design (although,
ironically, modules are probably the least committee-designed part of
ES6 :) ):

  - Some want modules in the conventional sense, as encapsulated
namespaces with named exports, which you can import and access
qualified or unqualified, and where imports are checked.

  - Some want modules in the specific pre-ES6 JavaScript style, where
they can be any arbitrary JS value, and in the good old JavaScript
tradition that checking doesn't matter.

The current design (including the newest suggestions for imports)
seems to please neither side, because it tries to be the former
semantically, but wants to optimise for the latter syntactically. The
main outcome is confusion.

* This is probably the 3rd or even 4th time round this aspect of
modules is discussed controversially. That is not a good sign. I
_really_ think we need to make up our minds:

  - Either we think real modules are an improvement, and checking is
important. Then the model and the syntax should be consistent about
that. Moreover, checking needs to consistently apply, no matter how a
module and its components are defined or accessed.

  - Or we come to the conclusion that supporting the legacy singleton
export model as a primary use case is a mandatory matter. Then we
should drop attempts of building something in/semi-compatible, and
limit innovation to making export and import declarative, and
designing a loader API.

The current design falls between stools with respect to syntax,
leading to the confusion people complain about. And it falls between
stools with respect to import checking, making it dependent on
superficially syntactic choices (like, whether you use default export
or not, or whether you use unqualified import or not), and thereby
unreliable in practice.

Quite honestly, I rather have no import checking than checking that
only applies in some syntactic cases -- because that gives a false
sense of security, harms refactoring, and/or encourages overuse of
unqualified imports, hampering readability. And if we are willing to
cut partial checking, then there actually is much less compelling
reason to have all the machinery around module objects, import as
aliasing, etc. The system could probably be simplified quite a bit,
and get much closer to what proponents of legacy JS modules are used
to.

Of course, I'd much rather go with real modules. But more
importantly, the system should make a choice. Something in the middle
is looking more and more like the least attractive alternative -- it
seems like substantial extra complexity for too little (or even
negative) benefit. As surprising as it may sound to some, I'm starting
to warm up to the legacy option if it avoids the floor between the
stools. :)

/Andreas


On 19 June 2014 10:15, David Herman dher...@mozilla.com wrote:
 Thanks to everyone for working through the issues around ModuleImport. I know 
 it's been frustrating, but the discussions have really helped clarify the key 
 constraints.

 ## Constraints

 First, let me restate the most important arguments. In favor of removal:

 * **The syntactic distinction between ModuleImport and default import is 
 vague.**

 We've consistently seen confusion between the semantics of ModuleImport and 
 default export. While certainly some of the confusion might be chalked up to 
 misinformation and lack of documentation, we've seen people be confused by 
 this even when correctly explained the semantics. The problem with the syntax 
 is that the only visual distinction is the initial keyword (`module` vs 
 `import`), and it's not clear from that keyword which concept you're talking 
 about. (Once you've internalized the structure of module instance objects, 
 you get a hint from the `module` keyword, but that doesn't help people who 
 are just learning the system, particularly if they're already familiar with 
 other JS module systems.)

 Against removal:

 * **Without ModuleImport, authors of multi-export modules would be pressured 
 to circumvent the named exports functionality.**

 Without ModuleImport, clients 

Re: ModuleImport

2014-06-27 Thread Kevin Smith


   - Either we think real modules are an improvement, and checking is
 important. Then the model and the syntax should be consistent about
 that. Moreover, checking needs to consistently apply, no matter how a
 module and its components are defined or accessed.

   - Or we come to the conclusion that supporting the legacy singleton
 export model as a primary use case is a mandatory matter. Then we
 should drop attempts of building something in/semi-compatible, and
 limit innovation to making export and import declarative, and
 designing a loader API.


Since real modules are at the core of the current design, I think the
first option is feasible and equates to simply dropping the default
feature, leaving everything else intact.  The second option, on the other
hand, will take us back to the drawing board and I don't see how we can do
that within the ES6 timeline.  We don't want Promises all over again.

So, if we cannot settle on option 1, then I think modules must be deferred
from ES6.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-27 Thread Matthew Robb
My opinion is that CommonJS and AMD work today and will continue to work
into the future so we should optimize for the ideal looking forward, not
backward case when adding to the language. Loader will still be
overload-able and since both CommonJS and AMD require a library today it
seems completely reasonable that they will continue to do that and can hook
into es6 through loader extension.

Conclusions:
- Drop default exports
- export function readFile(){}
- import fs from es6-fs; // fs.readfile();
- import { readFile } from es6-fs; // readFile();
- Done.


- Matthew Robb


On Fri, Jun 27, 2014 at 6:32 AM, Kevin Smith zenpars...@gmail.com wrote:


   - Either we think real modules are an improvement, and checking is
 important. Then the model and the syntax should be consistent about
 that. Moreover, checking needs to consistently apply, no matter how a
 module and its components are defined or accessed.

   - Or we come to the conclusion that supporting the legacy singleton
 export model as a primary use case is a mandatory matter. Then we
 should drop attempts of building something in/semi-compatible, and
 limit innovation to making export and import declarative, and
 designing a loader API.


 Since real modules are at the core of the current design, I think the
 first option is feasible and equates to simply dropping the default
 feature, leaving everything else intact.  The second option, on the other
 hand, will take us back to the drawing board and I don't see how we can do
 that within the ES6 timeline.  We don't want Promises all over again.

 So, if we cannot settle on option 1, then I think modules must be deferred
 from ES6.


 ___
 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-27 Thread Domenic Denicola
From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Kevin 
Smith

 The second option, on the other hand, will take us back to the drawing board 
 and I don't see how we can do that within the ES6 timeline.

We should not be concerned about timeframe in terms of what official Ecma spec 
revision modules land in. ES has moved to a train model, recognizing that it's 
more important when features ship in browsers than when Ecma publishes a 
copyrighted document containing the features. Modules are probably in stage 2, 
verging on stage 3, of [the TC39 process][1]. They won't make it into ES6 until 
they land in stage 4, and no implementation has started on them. It's not clear 
to me that keeping the current design would actually incentivize implementers 
to implement them any faster than if they dropped back to stage 1, especially 
since implementers generally prioritize features with high user demand, whereas 
modules in their current state are definitely mixed signals.

[1]: 
https://docs.google.com/document/d/1QbEE0BsO4lvl7NFTn5WXWeiEIBfaVUF7Dk0hpPpPDzU/edit
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: ModuleImport

2014-06-27 Thread Domenic Denicola
From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Matthew 
Robb

 My opinion is that CommonJS and AMD work today and will continue to work into 
 the future so we should optimize for the ideal looking forward, not 
 backward case when adding to the language.

While this is a compelling argument in general, I am not sure it applies to 
modules, whose usefulness is based almost entirely on network effects. Indeed, 
the future we may be looking forward to is just one in which ES6 modules remain 
a [third competing standard][1] among the modules in the wild, and if they're 
sufficiently bad at satisfying existing use cases (as the rest of your message 
argues for), they will not compete very well.


[1]: https://xkcd.com/927/
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-27 Thread Kevin Smith


 We should not be concerned about timeframe in terms of what official Ecma
 spec revision modules land in. ES has moved to a train model, recognizing
 that it's more important when features ship in browsers than when Ecma
 publishes a copyrighted document containing the features.


Fair enough - but the point still remains:  the second option pushes us
backward.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-27 Thread John Barton
+1


On Fri, Jun 27, 2014 at 6:39 AM, Matthew Robb matthewwr...@gmail.com
wrote:

 My opinion is that CommonJS and AMD work today and will continue to work
 into the future so we should optimize for the ideal looking forward, not
 backward case when adding to the language. Loader will still be
 overload-able and since both CommonJS and AMD require a library today it
 seems completely reasonable that they will continue to do that and can hook
 into es6 through loader extension.

 Conclusions:
 - Drop default exports
 - export function readFile(){}
 - import fs from es6-fs; // fs.readfile();
 - import { readFile } from es6-fs; // readFile();
 - Done.


 - Matthew Robb


 On Fri, Jun 27, 2014 at 6:32 AM, Kevin Smith zenpars...@gmail.com wrote:


   - Either we think real modules are an improvement, and checking is
 important. Then the model and the syntax should be consistent about
 that. Moreover, checking needs to consistently apply, no matter how a
 module and its components are defined or accessed.

   - Or we come to the conclusion that supporting the legacy singleton
 export model as a primary use case is a mandatory matter. Then we
 should drop attempts of building something in/semi-compatible, and
 limit innovation to making export and import declarative, and
 designing a loader API.


 Since real modules are at the core of the current design, I think the
 first option is feasible and equates to simply dropping the default
 feature, leaving everything else intact.  The second option, on the other
 hand, will take us back to the drawing board and I don't see how we can do
 that within the ES6 timeline.  We don't want Promises all over again.

 So, if we cannot settle on option 1, then I think modules must be
 deferred from ES6.


 ___
 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: ModuleImport

2014-06-27 Thread Kevin Smith
 +1


Yeah - obviously +1 from me as well.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-27 Thread Russell Leggett
On Fri, Jun 27, 2014 at 3:52 AM, Michał Gołębiowski m.go...@gmail.com
wrote:

 On Fri, Jun 27, 2014 at 9:44 AM, Russell Leggett 
 russell.legg...@gmail.com wrote:

 No, that example would be:

 import mkdirp as mkdir;

 Its actually shorter than node.


 But in current proposal the module object cannot be a function from what I
 understand. So you'd have to create a named export and import it as I wrote.


Ok, so can I just ask a serious question. I looked at the mkdirp library,
and in their own documentation, they use:

var mkdirp = require('mkdirp');
So let's say in the new world order, no default exports, this is a named
export mkdirp. Is it *really* that bad a thing to just use the name they
chose for their API? I mean what about all of the likely cases of exporting
a class. Would you advocate for those classes to be aliased before use?
What about methods? Those are typically unchanged. The argument has been
made that without default exports, library users would then have to known
the name of the exported member. Is that really a serious complaint? You
*have* to know what everything else is called, what parameters are
expected, etc. I would go as far as to say that either 1 of 2 things is
happening.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-27 Thread Kevin Smith



 var mkdirp = require('mkdirp');


Exactly.  In ES, you would see this:

import { mkdrip } from mkdirp;

Python has a somewhat similar module system, and import-renaming is the
exception, not the rule.  Also, I've never heard anyone complain about
having to know the name of a module member.  In fact, specifying the
exported name is essential for tracing out a code base that you're
unfamiliar with.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-27 Thread Russell Leggett


 Ok, so can I just ask a serious question. I looked at the mkdirp library,
 and in their own documentation, they use:

 var mkdirp = require('mkdirp');
 So let's say in the new world order, no default exports, this is a named
 export mkdirp. Is it *really* that bad a thing to just use the name they
 chose for their API? I mean what about all of the likely cases of exporting
 a class. Would you advocate for those classes to be aliased before use?
 What about methods? Those are typically unchanged. The argument has been
 made that without default exports, library users would then have to known
 the name of the exported member. Is that really a serious complaint? You
 *have* to know what everything else is called, what parameters are
 expected, etc. I would go as far as to say that either 1 of 2 things is
 happening.



Ok, accidentally sent...  either 1 of 2 things is happening

1) The imported function is always called the same thing when imported. Its
a de facto standard.
2) There is no de facto standard, and people call it a variety of things.

I would argue that 1 is easy to transition, just export with that name, and
2 is not really a good thing. Its much harder to read or grep your code. It
is an anti-pattern that should not be given so much sugar. Aliasing is
still possible, but more awkward.

I know Kevin and I both said this, but IMO the reason this pattern became
so popular was to avoid:

var mkdirp = require(mkdirp).mkdirp;

In my proposal (no curlies), that's simply:

import mkdirp from mkdirp;

The big thing missing is just ease of aliasing, and I don't really see that
as a problem. I'd love to hear an argument for why I'm wrong.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-27 Thread Russell Leggett
On Fri, Jun 27, 2014 at 10:11 AM, Kevin Smith zenpars...@gmail.com wrote:



 var mkdirp = require('mkdirp');


 Exactly.  In ES, you would see this:

 import { mkdrip } from mkdirp;

 Python has a somewhat similar module system, and import-renaming is the
 exception, not the rule.  Also, I've never heard anyone complain about
 having to know the name of a module member.  In fact, specifying the
 exported name is essential for tracing out a code base that you're
 unfamiliar with.


Haha, yes, you and I seem to be sharing a brain on this, I sent early and
you wrote most of what I wrote. I still like curly-free, but that's
bikeshedding to me. The important point is removing default exports.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-27 Thread Calvin Metcalf
I wrote up a gist summarizing the different proposals that were being
tossed around, it mainly says the same things as Andreas, just not as well
https://gist.github.com/calvinmetcalf/5d9a88abaa9fe094e960\


On Fri, Jun 27, 2014 at 10:02 AM, Kevin Smith zenpars...@gmail.com wrote:


 +1


 Yeah - obviously +1 from me as well.


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




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


RE: ModuleImport

2014-06-27 Thread Domenic Denicola
This might be a good time to bring up this old thing:

https://gist.github.com/domenic/1ab3f0daa7b37859ce43

At the time Yehuda and I put it together, we were much younger and more naive, 
but upon cursory review it seems not-horrible. It gives up mutable bindings but 
retains statically-verifiable multi-exports, along with a unified import syntax 
that doesn't require knowledge of how the module creator exported their 
objects, and exposes no refactoring hazards for transitioning between styles.

I just realize it is probably not very compatible with computed property names 
though :(

From: Andreas Rossbergmailto:rossb...@google.com
Sent: ‎2014-‎06-‎27 09:07
To: David Hermanmailto:dher...@mozilla.com
Cc: es-discuss@mozilla.orgmailto:es-discuss@mozilla.org
Subject: Re: ModuleImport

Some observations:

* I think the 'import * as x' syntax for module imports is not an
improvement, for at least two reasons:

  - It raises the expectation that you can actually write 'import *
from' (as already noted in this thread).

  - It removes the syntactic marker for binding a module identifier.
That is problematic because (a) module identifiers come with extra
static checks on their uses (or so I thought, see below), and it is
(b) future hostile to lexical module declarations, because with those,
only module identifiers could be used in certain contexts (e.g., on
the RHS of an import-from). Thinking forward, I think it would be
highly preferable to consistently mark all bindings of module
identifiers with a 'module' keyword.

* I think the controversy is because the module design tries pleasing
two incompatible community goals, but instead of achieving that, it
has acquired all the characteristics of a committee design (although,
ironically, modules are probably the least committee-designed part of
ES6 :) ):

  - Some want modules in the conventional sense, as encapsulated
namespaces with named exports, which you can import and access
qualified or unqualified, and where imports are checked.

  - Some want modules in the specific pre-ES6 JavaScript style, where
they can be any arbitrary JS value, and in the good old JavaScript
tradition that checking doesn't matter.

The current design (including the newest suggestions for imports)
seems to please neither side, because it tries to be the former
semantically, but wants to optimise for the latter syntactically. The
main outcome is confusion.

* This is probably the 3rd or even 4th time round this aspect of
modules is discussed controversially. That is not a good sign. I
_really_ think we need to make up our minds:

  - Either we think real modules are an improvement, and checking is
important. Then the model and the syntax should be consistent about
that. Moreover, checking needs to consistently apply, no matter how a
module and its components are defined or accessed.

  - Or we come to the conclusion that supporting the legacy singleton
export model as a primary use case is a mandatory matter. Then we
should drop attempts of building something in/semi-compatible, and
limit innovation to making export and import declarative, and
designing a loader API.

The current design falls between stools with respect to syntax,
leading to the confusion people complain about. And it falls between
stools with respect to import checking, making it dependent on
superficially syntactic choices (like, whether you use default export
or not, or whether you use unqualified import or not), and thereby
unreliable in practice.

Quite honestly, I rather have no import checking than checking that
only applies in some syntactic cases -- because that gives a false
sense of security, harms refactoring, and/or encourages overuse of
unqualified imports, hampering readability. And if we are willing to
cut partial checking, then there actually is much less compelling
reason to have all the machinery around module objects, import as
aliasing, etc. The system could probably be simplified quite a bit,
and get much closer to what proponents of legacy JS modules are used
to.

Of course, I'd much rather go with real modules. But more
importantly, the system should make a choice. Something in the middle
is looking more and more like the least attractive alternative -- it
seems like substantial extra complexity for too little (or even
negative) benefit. As surprising as it may sound to some, I'm starting
to warm up to the legacy option if it avoids the floor between the
stools. :)

/Andreas


On 19 June 2014 10:15, David Herman dher...@mozilla.com wrote:
 Thanks to everyone for working through the issues around ModuleImport. I know 
 it's been frustrating, but the discussions have really helped clarify the key 
 constraints.

 ## Constraints

 First, let me restate the most important arguments. In favor of removal:

 * **The syntactic distinction between ModuleImport and default import is 
 vague.**

 We've consistently seen confusion between the semantics of ModuleImport

Re: ModuleImport

2014-06-27 Thread Kevin Smith
 My opinion is that CommonJS and AMD work today and will continue to work
 into the future so we should optimize for the ideal looking forward, not
 backward case when adding to the language.


I think this statement points the way to something that we haven't yet
discussed.

A general question that we can apply to any language enhancement is:  does
this change merely satisfy existing users, or does this change carry the
potential to expand the user base?

I would say that Node-module-sugar would merely satisfy existing users,
but real modules have the capacity to expand the JS user base to into
segments that want static checking to be a part of their workflow.

So to me the path forward is clear:  we keep real modules, axe the default
feature, and take a temporary hit of dissatisfaction from existing users so
that we can expand the JS user base.

The overriding concern should be the long-term viability of JS.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-27 Thread C. Scott Ananian
On Fri, Jun 27, 2014 at 9:07 AM, Andreas Rossberg rossb...@google.com
wrote:

   - It removes the syntactic marker for binding a module identifier.
 That is problematic because (a) module identifiers come with extra
 static checks on their uses (or so I thought, see below), and it is
 (b) future hostile to lexical module declarations, because with those,
 only module identifiers could be used in certain contexts (e.g., on
 the RHS of an import-from). Thinking forward, I think it would be
 highly preferable to consistently mark all bindings of module
 identifiers with a 'module' keyword.


I disagree here.  I think certain people are too hung up on what is a real
module and what is an object pretending to be a module.  For lots of
legacy code (think jquery), we have objects like `$` which are actually
both functions *and* modules (in the form of namespaces).  The JS community
can handle this.  Honestly, most of the fun features of real modules are
obscure corner cases anyway (like lazy binding).  We can deal with a few
oddball modules which are not actually module objects.


   - Some want modules in the conventional sense, as encapsulated
 namespaces with named exports, which you can import and access
 qualified or unqualified, and where imports are checked.

   - Some want modules in the specific pre-ES6 JavaScript style, where
 they can be any arbitrary JS value, and in the good old JavaScript
 tradition that checking doesn't matter.

 The current design (including the newest suggestions for imports)
 seems to please neither side, because it tries to be the former
 semantically, but wants to optimise for the latter syntactically. The
 main outcome is confusion.


I think the problem is somewhat different, in that certain people resist
the idea that some modules might not be actual modules.  I think we could
embrace that and the result would be *less* confusion (since we wouldn't
require a syntactic marker for real module).  It will be rare for someone
to notice that `$.foo` is not lazily-bound, or that `$.module.path` (or
whatever) isn't actually defined.  If they care, they can file a bug
against jquery.  jquery should be able to either emulate the module
functionality (duck typing!  but this is one of the things that annoys me
about the current way lazy binding works) or decide that
backwards-compatibility or whatever is more important and ignore the issue.


   - Either we think real modules are an improvement, and checking is
 important. Then the model and the syntax should be consistent about
 that. Moreover, checking needs to consistently apply, no matter how a
 module and its components are defined or accessed.

   - Or we come to the conclusion that supporting the legacy singleton
 export model as a primary use case is a mandatory matter. Then we
 should drop attempts of building something in/semi-compatible, and
 limit innovation to making export and import declarative, and
 designing a loader API.


Again, I think it's the either/or mindset which is the problem here.  We
can actually have both.  Sometimes we won't be able to do strict checking.
 Sometimes we will.  We don't need to force everyone into the same mold.
 Let the author of the module decide how important static checking, lazy
binding, ease-of-use, etc, is and define their module appropriately.  (And
the same for the importer of the module.)


 Quite honestly, I rather have no import checking than checking that
 only applies in some syntactic cases -- because that gives a false
 sense of security, harms refactoring, and/or encourages overuse of
 unqualified imports, hampering readability.


Again: is this what's hampering compromise?  Can't we let the module author
(and/or importer) decide the extent to which they think checking is
important?

Yes, modules will be a compromise design.  But it's a compromise design
because of *network effects* and *programmer preference*.  There are large
and useful codebases organized around different principles.  We can't force
them all into the same mold.  Programming is still an art form and a matter
of taste; let's go easy on the mandates.
  --scott (who actually thinks that current modules spec is not that bad,
although it could be slightly improved)
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Re: ModuleImport

2014-06-27 Thread Brian Di Palma
I'm echoing Kevin here.

I'd hope ES6 modules would offer me, a programmer working on large
complex JS web apps, something more then what CommonJS/AMD offers.
I work with codebases of 1K+ JS classes, 200K+ LOC and with many
dependecies that are updated frequently.
When our teams update depedencies the more static fast failures we can
get compared to silent bugs the better.

I will eat my hat if in 10 years people will be doing greenfield
development using CommonJS/AMD instead of ES6 modules.

Provide the language users with something *better* then what we have,
don't just match it.

I like CommonJS, npm, node as they offer great solutions given their
constraints.
This is the language level though, the expressive power and
constraints are different.

Knowing the name of a module export is not an issue, it's not an issue
for people using global scripts or any other module systems/languages.
I'd prefer a real module system.
Especially considering that classes are being added and when you are
building front end applications with a lot of state classes fit well.
I can see many applications being mainly composed of modules with a
single class exported and the most logical export name would be the
classname.
I've tried to use default exports for these situations and they don't
seem to offer much value at all.

import {MyClass} from './myclass';

The value of default exports seems low here.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-27 Thread Andreas Rossberg
On 27 June 2014 18:36, C. Scott Ananian ecmascr...@cscott.net wrote:
 On Fri, Jun 27, 2014 at 9:07 AM, Andreas Rossberg rossb...@google.com
 wrote:

   - It removes the syntactic marker for binding a module identifier.
 That is problematic because (a) module identifiers come with extra
 static checks on their uses (or so I thought, see below), and it is
 (b) future hostile to lexical module declarations, because with those,
 only module identifiers could be used in certain contexts (e.g., on
 the RHS of an import-from). Thinking forward, I think it would be
 highly preferable to consistently mark all bindings of module
 identifiers with a 'module' keyword.

 I disagree here.  I think certain people are too hung up on what is a real
 module and what is an object pretending to be a module.  For lots of
 legacy code (think jquery), we have objects like `$` which are actually both
 functions *and* modules (in the form of namespaces).  The JS community can
 handle this.  Honestly, most of the fun features of real modules are
 obscure corner cases anyway (like lazy binding).  We can deal with a few
 oddball modules which are not actually module objects.

I think you are missing the central problem. If imports/exports are to
be statically checked, then module bindings, their exports, and their
uses have to be statically recognisable and analysable. That prohibits
intermixing proper modules with other random objects. Furthermore,
it also requires module identifiers to be distinguishable by context.
(And my point above was that, since this matters for the semantics,
the programmer is best served when she can immediately distinguish
binding forms accordingly.)

   - Some want modules in the conventional sense, as encapsulated
 namespaces with named exports, which you can import and access
 qualified or unqualified, and where imports are checked.

   - Some want modules in the specific pre-ES6 JavaScript style, where
 they can be any arbitrary JS value, and in the good old JavaScript
 tradition that checking doesn't matter.

 The current design (including the newest suggestions for imports)
 seems to please neither side, because it tries to be the former
 semantically, but wants to optimise for the latter syntactically. The
 main outcome is confusion.

 I think the problem is somewhat different, in that certain people resist the
 idea that some modules might not be actual modules.  I think we could
 embrace that and the result would be *less* confusion (since we wouldn't
 require a syntactic marker for real module).  It will be rare for someone
 to notice that `$.foo` is not lazily-bound, or that `$.module.path` (or
 whatever) isn't actually defined.  If they care, they can file a bug against
 jquery.  jquery should be able to either emulate the module functionality
 (duck typing!  but this is one of the things that annoys me about the
 current way lazy binding works) or decide that backwards-compatibility or
 whatever is more important and ignore the issue.

You argue that throwing out checking is fine, i.e., you are arguing
for the second goal, and against the first. But others disagree.

   - Either we think real modules are an improvement, and checking is
 important. Then the model and the syntax should be consistent about
 that. Moreover, checking needs to consistently apply, no matter how a
 module and its components are defined or accessed.

   - Or we come to the conclusion that supporting the legacy singleton
 export model as a primary use case is a mandatory matter. Then we
 should drop attempts of building something in/semi-compatible, and
 limit innovation to making export and import declarative, and
 designing a loader API.

 Again, I think it's the either/or mindset which is the problem here.  We
 can actually have both.  Sometimes we won't be able to do strict checking.
 Sometimes we will.  We don't need to force everyone into the same mold.  Let
 the author of the module decide how important static checking, lazy binding,
 ease-of-use, etc, is and define their module appropriately.  (And the same
 for the importer of the module.)

 Quite honestly, I rather have no import checking than checking that
 only applies in some syntactic cases -- because that gives a false
 sense of security, harms refactoring, and/or encourages overuse of
 unqualified imports, hampering readability.

 Again: is this what's hampering compromise?  Can't we let the module author
 (and/or importer) decide the extent to which they think checking is
 important?

No, the importers have no choice, they have to go with whatever the
module provider picked. You cannot turn on checking on the use site
alone, because it will lack the necessary static information from the
definition site. Only real modules can provide that information,
because only their definitions are sufficiently structured. That is
fundamentally so. The hybrid, best of both worlds approach you seem to
have in mind is technically impossible, unfortunately.

/Andreas

Re: ModuleImport

2014-06-27 Thread C. Scott Ananian
On Fri, Jun 27, 2014 at 3:17 PM, Andreas Rossberg rossb...@google.com
wrote:

 I think you are missing the central problem. If imports/exports are to
 be statically checked, then module bindings, their exports, and their
 uses have to be statically recognisable and analysable. That prohibits
 intermixing proper modules with other random objects.


No, it means that your checker will only work with 'proper' modules.  The
linter can easily have a white/blacklist to handle oddball cases.

You argue that throwing out checking is fine, i.e., you are arguing
 for the second goal, and against the first. But others disagree.


No.  I believe that *allowing the user (or module author) to selectively
ignore* the checking (for example, by using a default import of an object
which is not a module).  You seem to be missing my fundamental point: this
is not a dichotomy.  You can check many imports, even if you can't check
all.  If the module author chooses to export a function instead of an
object, you can't check the imports of *that one module*.  Use a different
module if that bothers you!

No, the importers have no choice, they have to go with whatever the
 module provider picked.


The importers have the choice to use a different module (or fork the
module, or use a transpiler, or...).

The module author has the choice to re/structure his module to allow lazy
binding/checking *iff the users demand*.


 The hybrid, best of both worlds approach you seem to
 have in mind is technically impossible, unfortunately.


I look forward to a technical proof then.  You have not yet provided that.
 --scott
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-27 Thread Andreas Rossberg
On 27 June 2014 17:32, Kevin Smith zenpars...@gmail.com wrote:
 So to me the path forward is clear:  we keep real modules, axe the default
 feature, and take a temporary hit of dissatisfaction from existing users so
 that we can expand the JS user base.

Note that the other half of my argument was that real modules are
only worth the complexity when they provide checking _consistently_.
That is, it shouldn't matter whether I write

  import {f, g, h} from url
  f(); g(); h()

or

  module M from url
  M.f(); M.g(); M.h()

These should be freely interchangeable -- the programmer shouldn't
need to pick between getting import checking but polluting the scope
and making uses less readable, or the other way round. The current
semantics falls short on that, it doesn't check in the latter case.

So from my perspective, that would need to be fixed as well. Which
would be fairly easy.

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


Re: ModuleImport

2014-06-27 Thread Kevin Smith

   import {f, g, h} from url
   f(); g(); h()

 or

   module M from url
   M.f(); M.g(); M.h()

 These should be freely interchangeable -- the programmer shouldn't
 need to pick between getting import checking but polluting the scope
 and making uses less readable, or the other way round. The current
 semantics falls short on that, it doesn't check in the latter case.


I didn't even realize that was the case.



 So from my perspective, that would need to be fixed as well. Which
 would be fairly easy.


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


Re: ModuleImport

2014-06-27 Thread Andreas Rossberg
On 27 June 2014 21:26, C. Scott Ananian ecmascr...@cscott.net wrote:
 On Fri, Jun 27, 2014 at 3:17 PM, Andreas Rossberg rossb...@google.com
 wrote:

 I think you are missing the central problem. If imports/exports are to
 be statically checked, then module bindings, their exports, and their
 uses have to be statically recognisable and analysable. That prohibits
 intermixing proper modules with other random objects.

 No, it means that your checker will only work with 'proper' modules.  The
 linter can easily have a white/blacklist to handle oddball cases.

 You argue that throwing out checking is fine, i.e., you are arguing
 for the second goal, and against the first. But others disagree.

 No.  I believe that *allowing the user (or module author) to selectively
 ignore* the checking (for example, by using a default import of an object
 which is not a module).  You seem to be missing my fundamental point: this
 is not a dichotomy.  You can check many imports, even if you can't check
 all.  If the module author chooses to export a function instead of an
 object, you can't check the imports of *that one module*.  Use a different
 module if that bothers you!

 No, the importers have no choice, they have to go with whatever the
 module provider picked.

 The importers have the choice to use a different module (or fork the module,
 or use a transpiler, or...).

 The module author has the choice to re/structure his module to allow lazy
 binding/checking *iff the users demand*.

All this means is that there will effectively be two different module
systems, and in practice, every module provider has to pick one. Which
is a problem, not a solution.

 The hybrid, best of both worlds approach you seem to
 have in mind is technically impossible, unfortunately.

 I look forward to a technical proof then.  You have not yet provided that.

Well, I don't know how it could be done. I think the proof obligation
is on those who claim it's possible. ;)

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


Re: ModuleImport

2014-06-27 Thread C. Scott Ananian
On Fri, Jun 27, 2014 at 3:34 PM, Andreas Rossberg rossb...@google.com
wrote:

 All this means is that there will effectively be two different module
 systems, and in practice, every module provider has to pick one. Which
 is a problem, not a solution.


...this is why I've been arguing strongly for consistent syntax regardless.
 Static checking and lazy binding should be value added features, not
something I have to think about every time I import a module.

 The hybrid, best of both worlds approach you seem to
  have in mind is technically impossible, unfortunately.
 
  I look forward to a technical proof then.  You have not yet provided
 that.

 Well, I don't know how it could be done. I think the proof obligation
 is on those who claim it's possible. ;)


jslint/jshint is already a (hacky) proof for the most common cases.  It
detects undeclared variables.  All you need to do is write a loader which
will prepopulate the jshint's 'predef' field appropriately.

More complicated sorts of static checking fall to Turing completeness.  Ie:

```
import foo from foo;

var bat = (Math.random()  1) ? foo : { };

console.log(bat.baz); // is this a static error?
```

The reasonable thing is to accept incompleteness and provide static
checking of the common cases: barewords and module name.identifier
productions.  Both of those tests are quite capable of skipping tests if
module name is not a pure module.
 --scott
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-27 Thread Kevin Smith


 
  The module author has the choice to re/structure his module to allow lazy
  binding/checking *iff the users demand*.

 All this means is that there will effectively be two different module
 systems, and in practice, every module provider has to pick one. Which
 is a problem, not a solution.



Right - and this piles complexity on top of complexity, from both the
user's point of view and the implementer's/analyzer's point of view.  If
you're going to demand such complexity, then you at least have to back it
up with some real, concrete advantages.  What are they?  Bullet points are
good.  : )

Just so we agree what we're talking about, this is the default-default
solution, right?
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-27 Thread Marius Gundersen
On 27 Jun 2014 21:29, Andreas Rossberg rossb...@google.com wrote:

 Note that the other half of my argument was that real modules are
 only worth the complexity when they provide checking _consistently_.
 That is, it shouldn't matter whether I write

   import {f, g, h} from url
   f(); g(); h()

 or

   module M from url
   M.f(); M.g(); M.h()

 These should be freely interchangeable -- the programmer shouldn't
 need to pick between getting import checking but polluting the scope
 and making uses less readable, or the other way round. The current
 semantics falls short on that, it doesn't check in the latter case.

 So from my perspective, that would need to be fixed as well. Which
 would be fairly easy.

 /Andreas

And this is yet another counter argument to the default export. If the
default export is an object with properties (or a function with properties,
which I quite common in npm) then there is no static checking of those
properties. So with today's spec there is one way to get static checking
and one ways (default)  to not get static checking.

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


Re: Re: ModuleImport

2014-06-27 Thread Brian Di Palma
Andreas, I hope you're not just getting my hopes up with the
possibility of checking ModuleImports too.
That would be great. I was disappointed that they weren't originally.

Making

module fs from 'fs';

fs.readFile(...);

and

import {readFile} from 'fs';

equivalent in terms of static checks is the right approach.

If the cost of these improvements is not having default exports it
seems acceptable.
In essence we would have to write

import {jquery} from 'jquery';

instead of

import jquery from 'jquery';

The flexibility of not having to know the export identifier is
worthless to me.
I can't see how I could make use of a module without reading some
documentation on it, which will show me the identifiers.

 Static checking and lazy binding should be value added features, not 
 something I have to think about every time I import a module.

I don't understand how you can make use of what you require without
reading some sort of documentation or code.
This will be an even smaller cost once tooling supports ES6 modules
as it will allow autocompletion of imports statements.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-26 Thread Kevin Smith
On Wed, Jun 25, 2014 at 4:50 PM, C. Scott Ananian ecmascr...@cscott.net
wrote:

 @John Barton:  Yes, ideally that syntax would work as well when you don't
 need a namespace.  But sometimes you do need a namespace, even if you don't
 care precisely what it is:
 ```
 import {format} from 'url';
 import {format} from 'util';
 import {connect} from 'tls';
 import {connect} from 'net';
 import {fork} from 'cluster';
 import {fork} from 'child_process';
 // etc
 ```


I agree, and importing as a namespace is what ModuleImport is all about.
 Crazy idea:  what if we had this:

// ModuleImport: import Identifier from StringLiteral
import fs from fs;
import url from url;

And just got rid of the default monkey-business?  Simple, no confusion, no
refactoring hazards.

Do we *really* need assignable default exports?  If we could jettison that
feature, it would (as John points out) make all of this pain go away.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-26 Thread Marius Gundersen
On Thu, Jun 26, 2014 at 8:15 AM, Kevin Smith zenpars...@gmail.com wrote:


 I agree, and importing as a namespace is what ModuleImport is all about.
  Crazy idea:  what if we had this:

 // ModuleImport: import Identifier from StringLiteral
 import fs from fs;
 import url from url;

 And just got rid of the default monkey-business?  Simple, no confusion, no
 refactoring hazards.

 Do we *really* need assignable default exports?  If we could jettison that
 feature, it would (as John points out) make all of this pain go away.


That would simplify the usage of modules (users wouldn't need to look up
which of the two ways the module author (arbitrarily) decided to use) and
it would simplify authoring of modules (only one way to export things). The
only real complaint we are likely to hear is that it would not allow single
export modules, which is the favoured usage of modules. I disagree with
this; a module that only exports one named thing is a single export module.
If you want to author a single export module then you only export one
thing, and users of your module only import one thing:

```js
//file AbstractSingletonProxyFactoryBean.js
export class AbstractSingletonProxyFactoryBean {
  //...
}

//file MyApp.js
import {AbstractSingletonProxyFactoryBean} from
AbstractSingletonProxyFactoryBean;

```
Now the author can choose to export more things later without making
breaking changes to the module. The only downside to this is the
(apparently mandatory) curly braces around the imported object. If single
export/import becomes the convention with ES6 modules then users will be
forced to type an extra pair of {} several times in most of their files. Is
the two extra characters something we can live with?

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


Re: ModuleImport

2014-06-26 Thread Kevin Smith

 Now the author can choose to export more things later without making
 breaking changes to the module. The only downside to this is the
 (apparently mandatory) curly braces around the imported object. If single
 export/import becomes the convention with ES6 modules then users will be
 forced to type an extra pair of {} several times in most of their files. Is
 the two extra characters something we can live with?



I have a good bit of experience coding ES modules, and I was worried about
that at first.  But hasn't been a problem for me.  Then again, I'm just one
person - it would be good to get more data from developers actually coding
with ES modules.

This syntax would make things completely obvious and simple though:  if
there's curly braces, then you're reaching into the bag and pulling out
things, and if there's no curly braces, you're getting the bag itself.
 There's even a visual analogy at play here:  the curly braces themselves
resemble the sides of a bag.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-26 Thread Russell Leggett
 Now the author can choose to export more things later without making
 breaking changes to the module. The only downside to this is the
 (apparently mandatory) curly braces around the imported object. If single
 export/import becomes the convention with ES6 modules then users will be
 forced to type an extra pair of {} several times in most of their files. Is
 the two extra characters something we can live with?



 I have a good bit of experience coding ES modules, and I was worried about
 that at first.  But hasn't been a problem for me.  Then again, I'm just one
 person - it would be good to get more data from developers actually coding
 with ES modules.

 This syntax would make things completely obvious and simple though:  if
 there's curly braces, then you're reaching into the bag and pulling out
 things, and if there's no curly braces, you're getting the bag itself.
  There's even a visual analogy at play here:  the curly braces themselves
 resemble the sides of a bag.


To me, though, that goes back to the destructuring/not destructuring
aspect. Maybe this has floated by during the bikeshedding, but why not
something like:

//import a single named export
import foo from bar;

//import multiple named exports
import foo, baz from bar;

//alias an imported named export
import foo as fooAlias from bar;

//import the module
import bar as bar;

So basically, just get rid of the {} for importing named exports, and move
the whole module import after the as. It reads better to me and I think is
more intuitive. As for default exports - I think they only make sense if
done the way it works in node. A single default export that effectively
replaces the module. Let's remember how it gets used in node:

var _ = require(underscore);

In node, if they didn't do it as a single export, then you would have to do:

var _ = require(underscore)._;

Given that underscore (and jquery and several others) are only a single
export, it would be annoying and error prone to do that all over the place.
The value added was for the importer - *not the exporter*. With the new
syntax I'm proposing, importing underscore would be exactly the same as
what the current proposal is for default export imports.

import _ from underscore;

Its just that underscore would have to have the named export _. As I said,
though, that's not really a burden, and the argument for default exports
was never really for the module writer.

There is one small case I'm missing, which is that default export imports
let you name the import whatever you want without writing extra code for
the alias. I don't really find that as a drawback, but then again, I do
write a lot of Java in addition to JavaScript. I don't really see any other
languages that operate this way either, and I would come back again to the
distinct history and constraints that JS/node has had up until now. If keep
that flexibility/matching semantics for smoothest continuity, I would
propose that default exports have to be a *single* default export, and that
it would replace module importing instead of export importing.

import underscore as _;

Where there is a single default export in the underscore module. This would
mean that the normal module import semantics don't work in this case, but
that is the tradeoff decided by the module author. I personally don't think
its worth adding this feature, but if it were added, I would expect it to
work this way.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-26 Thread C. Scott Ananian
On Thu, Jun 26, 2014 at 10:50 AM, Russell Leggett russell.legg...@gmail.com
 wrote:

 To me, though, that goes back to the destructuring/not destructuring
 aspect. Maybe this has floated by during the bikeshedding, but why not
 something like:

 //import a single named export
 import foo from bar;

 //import multiple named exports
 import foo, baz from bar;

 //alias an imported named export
 import foo as fooAlias from bar;

 //import the module
 import bar as bar;


I like the fact that this doesn't look like destructuring, since variable
binding is different from destructuring assignment.  Could
```
import foo, baz from bar as bar;
```
allowed simultanous import of named exports and the module itself?  If so,
the grammar gains a pleasing regularity.

OTOH, I think this syntax reorganization is orthogonal to some of the other
issues discussed.  In particular, your latter proposal still allows for
user confusion between:
```
import _ from underscore;
import underscore as _;
```
The various proposals seem to try to address this by making these
semantically identical (or near-identical, with some cooperation from the
module author).
 --scott
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleImport

2014-06-26 Thread Mark Volkmann
On Thu, Jun 26, 2014 at 9:50 AM, Russell Leggett russell.legg...@gmail.com
wrote:


 To me, though, that goes back to the destructuring/not destructuring
 aspect. Maybe this has floated by during the bikeshedding, but why not
 something like:

 //import a single named export
 import foo from bar;

 //import multiple named exports
 import foo, baz from bar;

 //alias an imported named export
 import foo as fooAlias from bar;

 //import the module
 import bar as bar;

 So basically, just get rid of the {} for importing named exports, and move
 the whole module import after the as.


Yes! I would SO much happier with this if the curly braces were removed.

-- 
R. Mark Volkmann
Object Computing, Inc.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


  1   2   >