`import` and aliasing bindings

David Herman dherman at mozilla.com
Fri Dec 28 08:54:17 PST 2012

On Dec 28, 2012, at 8:32 AM, Domenic Denicola <domenic at domenicdenicola.com> wrote:

>> Dave and Sam may have a different answer, but I'd answer that the aliasing semantics follows from a module system's role as (among other things) a name spacing mechanism.
> This idea of modules as namespaces is a very interesting one I hadn't considered. My experience is with C++/C# namespaces, and with ES5 modules. With only this experience, the two concepts seem worlds apart. Are there other precedents where something by the name of "modules" acts like C++/C# namespaces, e.g. Ruby or Python?

There are indeed. Scheme and ML are examples. (Erlang and Haskell aren't really relevant since their bindings are immutable.)

> If not, perhaps the feature should be renamed to avoid confusion?

The word "namespace" flies around with *many* meanings -- you won't get very far arguing about its true meaning. But in terms of language features, ES6 modules are far closer to the historical precedent of language features known as "modules" rather than language features known as "namespaces."

> You could argue that "most" ES programmers aren't using modules today, so preserving the intuitions of and making refactoring easier for that minority isn't valuable. You might be correct, but I think the most avid early adopters who will drive ES6 forward are precisely the ones using ES5 modules. Furthermore, many of those not using modules are using "namespaces" via global object hierarchies, which (without `with`) have no aliasing properties.

The aliasing isn't observable for immutable bindings, only for mutable ones. In my experience, all of the module exports I've seen from NPM modules I've used were immutable. Yehuda mentioned that he has seen mutable ones, but are they even common? To be clear, I'm not talking about an exported function that can produce different results when called multiple times (m.currentFoo()) -- that is not affected by the aliasing semantics -- and I'm not talking about an exported object whose contents are mutable (m.stuff.foo) -- that is also not affected by the aliasing semantics. I'm only talking about an export whose binding itself is mutated.

So I fully agree with all of Andreas's points. Another one is that I've been thinking we should add getter/setter exports to make it possible to create lazily initialized exports:

    let cell;
    export get foo() {
        if (!cell)
            cell = initialize();
        return cell.value;

It would be surprising for a getter property to extract its value at import time rather than reference time, and even more surprising for a setter property not to invoke the setter when mutated via an import. It would defeat the purpose of import. A big part of the reason for import to be a different form from let/var is for it to set up this aliasing relationship. If all it did was local binding, it would not be offering much that let/var don't already do.


More information about the es-discuss mailing list