On 03.04.2011 3:33, David Herman wrote:
Hi James,

1) Files as modules do not need module wrapper
====================
Just to confirm, if a JS file contains only a module definition, the
module X{} wrapper is not needed?
That's correct.
2) Set module export value
====================

Is it possible to support setting the value of the module to be a
function or some other value?
Currently, there's nothing like this in the proposal, but I remember you blogged about 
this before. Harmony modules are static entities, and setting their "value" 
dynamically would clash with the design goals of static importing and exporting.

That said, we could consider adding functionality to make a module callable, to 
address the use case you describe. Thanks for bringing this up.

3) Are "module" and "import" needed inside a module?
====================
There are two questions here:

3a) Is "module" needed inside a module?

Yes. A module declaration declares a binding to a static module. A let/var 
declaration declares a binding to a dynamic value. You only get compile-time 
linking and scoping with static modules.

3b) Is "import" needed inside a module?

I think the answer here is technically no. You're right that you could 
generally use let/var and destructuring, except for the import M.* case. If we 
allowed you to destructure a runtime expression and dynamically bind all its 
variables, we would be re-introducing `with' into Harmony, which we will never, 
ever, ever do. :)

Yes, since technically it's possible to get a value of an exported binding directly via:

let foo = Mod.foo;

then it should be possible to use destructuring to get references for several bindings.

However, as noticed, such imported via assignment bindings aren't static. I.e. it's possible e.g to assign to them in contrast if the binding is imported. Here I showed this difference: https://gist.github.com/885534 While this example is shown on prototyped modules in Narcissus, actually technically for real modules implementation there can be overloaded operator of assignment which calls `defineProperty` instead to make the binding the same as it was imported.

Regarding, "import M.*" via destructuring, it's also arguable whether we don't need it since it "looks like a with". Besides, if we can import all via "partial destructuring", i.e.:

module Mod {
    export foo var = 10;
    export bar var = 20;
}

let {foo, bar} = Mod;

then (theoretically!) why not to have `let {} = Mod` (or any other syntax, e.g. let * = Mod). But, IMO it just looks more complicated than import Mod.*. So I would disallow `let {} = Mod` not because of `with`, but because of the oddness of the construction which sounds as "destruct the module Mod into the empty object".

The other difference -- at least in the current state of the proposal -- is 
that you can't use a `require' form in an ordinary expression, only in the RHS 
of an import/module declaration. This doesn't show up in the Geometry example 
you cited, but if you wanted to import from an external module using `let', you 
would have to use the callback API:

     ModuleLoader.load("geometry.js", function(Geometry) {
         let { draw } = Geometry;
         ...
     });

(We've talked a little bit about generalizing the `require' form to be an 
expression operator that does a static module load, but I'm not sure whether it 
hangs together.)


This is the question of allowing expression which we talked in the Narcissus list (https://mail.mozilla.org/pipermail/narcissus/2011-March/000043.html ; btw, is it worth to put the discussing on duplications on this list?).

Though the other question is: why do we need `require` at all? Why not just:

// loading from the local file system

module $ = "./selector.js";

// loading from Net

module Widgets = "http://mysite.com/widgets.cs";;

Though, I see the only case with destructuring (assuming that the module isn't on local system):

let {foo, bar} = require "http://mysite.com/widgets.cs";

But since you notice that `require` won't be allowed in such expression, I don't see why it's needed at all.

Besides, I can imagine something like this:

import "widgets/panel"

which loads file "panel.js" from the "widgets" directory and either creates the module binding name as `Panel` (i.e corresponding to the file name), or imports all bindings from the module. Another variant:

import "widgets/panel" {foo, myBar: bar}

or

import {foo, myBar: bar} from "widgets/panel"

Dmitry.

The end goal is trying limit the number of new special things in the
language the developer needs to learn for modules. Ideally it would
be: "use 'module' to declare an inline module, then use require('')
inside it to get handles on other modules, and use var/let and
destructuring as you normally would".
For many cases, I think that's fine. But .* is an important convenience for 
scripting. Also, FWIW, import is already reserved and has symmetry with export, 
so it seems like a wasted opportunity to fill a natural space in the grammar.

4) How to optimize
====================
I think this is beyond the scope of ECMAScript.next. People are still figuring 
out how to optimize delivery, and web performance patterns are still shaking 
out. ISTM there will be situations where it's more performant to combine many 
modules into one (which can be done with nested module declarations) and others 
where it's more performant to conditionally/lazily load modules separately 
(which can be done with module loaders). I don't currently have a clear picture 
of how we could build syntactic conveniences or abstractions for doing this, 
but at least the pieces are there so programmers have the building blocks to 
start constructing their own tools for doing this.

5) Loader plugins
====================

Some of the AMD loaders support loader plugins[7].
Missing a reference in your bibliography. :)

This allows an AMD
module to load other types of resources, and a module can treat them
as a dependency.
I don't know-- I'd be interested to read more on this topic.

6) Loader API: multiple modules
====================

The loader API seems to only allow loading one module at a time with a
callback (looking at Loader.load). Is there a way to say "load these
three modules, and call this callback when all three are loaded"?
Perhaps. We're trying to get the building blocks in place first. We can figure 
out what conveniences are needed on top of that.

BTW, what you're asking for is essentially a concurrent join, which is 
convenient to express in a new library I'm working on called jsTask:

     let [m1, m2, m3] = yield join(load("m1.js"), load("m2.js"), load("m3.js"));

7) Cross-domain script loading
====================

Given the modules examples page, it looks like it will be possible to
load scripts from other domains, just confirming that it will be
allowed, particularly in the browser.
Yep!

Thanks for the questions,
Dave

_______________________________________________
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

Reply via email to