Modules first or second class (Re: I noted some open issues on "Classes with Trait Composition")

Claus Reinke claus.reinke at
Sun May 22 02:04:33 PDT 2011

> I think "modules are a construct that evaluates to an object"
> is the wrong way to think about them. Syntactic modules
> are a second-class construct that is not an expression. You
> can reflect on modules at runtime, and that reflection is
> provided as an object, but that's because almost all
> compound data structures in JS are objects. But I would
> advise against describing modules as a kind of object.

>> Just a note on this: for me, that means Harmony modules
>> are a step back from what I can implement in JS/now.
> How is it a step back, if you can already implement it? We're
> not taking objects away from JavaScript.

If I implement a module loader[1] in JS/now, my modules
are first-class functions from export objects to export object.
Normally, that is just used to model import dependencies,
but fully instantiated modules are (export) objects, and
first-class modules fit right into the pattern.

You're advising that thinking about Harmony modules
as first-class objects is not the best way to think about them.

Yes, I can continue to use first-class modules inside Harmony
modules, but that makes two separate concepts where there
used to be one.

>> Not
>> having first-class modules has been a major drawback in
>> Haskell (which has a strictly 1980s-style module system),
>> leading to all kinds of work-arounds.
> Usually when people deride the Haskell module system,
> they are comparing it to the ML module system, which...
> is also a second-class module system.

A hobby horse of mine [2, especially chapter 4 and sections

The proponents of Haskell's module system were explicitly
looking for something simple (just namespacing), so it is
not so much deriding as knowing that there are better
solutions. I added a first-class module system to a dynamically
typed functional language back in the 1990s, and from the
literature then, it seemed that some ML implementations
already had first-class modules (some had only higher-order
functors, first-class in the separate module language).

Naturally, since I spent a lot of time thinking about the
advantages of first-class modules, it is great to be able
to implement them, including loaders, so easily in

Modulo loaders, they are also easy in Haskell (I worked
in Mark Jones' group for a while - he did some nice work
in that area), but since most of the infrastructure is geared
towards the second-class modules, first-class modules
aren't used as much as their advantages would suggest.

>> One of these workarounds, which I expect to see and
>> use a lot in Harmony, is to have first-class modules-
>> as-records (or objects) inside second-class built-in-
>> modules.
>> Is this an intended outcome of the Harmony module design?
> That's kind of a loaded question, given the word "workaround"

No loading intended. I realize that the majority view might
not yet call for first-class modules, might therefore find them
counter-intuitive. Those developers might think of first-class
modules as an abstract complication, rather than a simplifying
and practical tool. It is just those who have grown used to their
advantages who need workarounds in second-class modules.

> but yes, it's definitely an intended outcome of the design to
> have second-class modules. Modules that are second-class
> have many benefits over first-class modules:
> - they are extremely lightweight, which is really important for ergonomics

I find modules-as-objects/records lightweight, but given the
discussions I've seen on the CommonJS list regarding module
formats, you're probably right for the majority of users.

> - they make it possible to do compile-time linking and variable resolution

For Javascript and other dynamic languages, compile-time
for one piece of code is often runtime for its host code.
Having a phase separation, after which all variables are
resolved, is great but is that not addressed by destructuring?

> - they can share static information, such as sets of bindings
> (note that import * would not work with first-class modules),
> macros, or types (both of which are, IMO, worth considering
> in the future for ECMAScript)

Import * is useful, but isn't it based on the fixed shape
of the module we import from? In a typed language, if there
is a static type that includes the property names of an object,
import * from that object becomes possible. And, in Javascript,
wouldn't a restricted 'with', working only on frozen objects,
serve the same purpose?

Btw, can I do 'import *' on a dynamically loaded module?

Types and modules are tricky, because of the various design
options (some of which are mentioned in section 8.2 of [2]).

> Moreover, loaders make it possible to do dynamic linking.
> It's just a little harder than in e.g. SML. I say that's the right
> trade-off: writing simple modules is trivial, and writing
> modules with pluggable dependencies is still possible.

And reflection represents module instances as objects. I
was just surprised that you insisted on the second-class
view as central (rather than it being a simplified view on
first-class modules).

Thanks for the clarification,

[2] Functions, Frames, and Interactions - completing a
    lambda-calculus-based purely functional language with
    respect to programming-in-the-large and interactions
    with runtime environments, Claus Reinke, 1998


More information about the es-discuss mailing list