On Oct 16, 2012, at 4:51 PM, John J Barton <[email protected]> wrote:

> On Tue, Oct 16, 2012 at 2:58 PM, David Herman <[email protected]> wrote:
>> The weird thing about (a) is that code that appears to be straight-line 
>> actually executes in somewhat more unpredictable (although deterministic) 
>> order.
> 
> I guess if we can handle deeply nested callbacks, event handlers, and
> promises, then this is a pretty tame as weird things go.  Are you are
> saying is that the body of the module does not run until we need its
> content? So dependents pull in their dependencies and modules that are
> not needed are not executed. That's what we want right?

My main concern comes from the fact that module initialization code can have 
arbitrary side effects: modify variables or shared objects, update the DOM, 
change some CSS, send an XHR request to fire a nuclear missile (HTTP UPDATE 
please -- I like my global thermonuclear war RESTful), ... You don't generally 
want languages to cause side effects to happen in unpredictable orders. If 
modules are executed on demand, you can't as easily predict when they are going 
to execute. (This is an instance of the general rule of PL design: lazy 
execution and side effects don't mix.)

But, that said, the execution of the modules isn't triggered by arbitrary 
control flow of the program, just the syntactically restricted top-level 
imports. So that probably makes it pretty tame.

Still, I'm interested in hearing Sam's and Andreas Rossberg's input on this.

>> The downside of (b) is that when you have cyclic dependencies, one module 
>> won't even be *partly* initialized before the other module starts running. 
>> (Although usually, when you have cyclic dependencies, you probably don't 
>> want to be evaluating exports from each other in top-level code -- you want 
>> all those mutual references to be happening under functions.)
> 
> I don't understand b, but dependency on internal vs external sounds bad.

Both (a) and (b) are meant to avoid dependency on internal vs external (unlike 
the system as currently described on the wiki). I didn't explain (b) very well. 
The idea would be that you would execute modules one at a time, rather than 
interleaved, but their order of execution would be topologically sorted by 
dependency. So if you don't have cyclic dependencies, you know that by the time 
you refer to an export of a module you depend on, it will have already been 
initialized. However, with cyclic dependencies, it's harder to understand what 
order they'll execute in, and you need to make sure not to refer to exports of 
a module until it's been fully initialized. By contrast, with (a), there's 
still a chance that you won't blow up.

Concrete example: Even and Odd modules refer to each other, but the import 
statements occur after some initialization:

    module Odd {
        export let odd = function(x) {
            return x === 0 ? false : !even(x - 1);
        }
        import even from Even; // force execution of Even here, if it hasn't 
already
        export let b = odd(17);
    }
    module Even {
        export let even = function(x) {
            return x === 0 || !odd(x - 1);
        }
        import odd from Odd; // force execution of Odd here, if it hasn't 
already
        export let b = even(17);
    }
    console.log(Odd.b);

With semantics (a), this executes like so:

- start executing Odd
- initialize Odd.odd
- start executing Even
- initialize Even.even
- try to start executing Odd (but it's already started, so don't)
- initialize Even.b by calling Even.even
- initialize Odd.b by calling Odd.odd

And everything succeeds. With semantics (b), regardless of how we break the tie 
in a cycle, this will fail, because it will try to call either Odd.odd or 
Even.even before it has initialized the function. Say it starts executing Odd 
first. It would do this:

- start executing Odd
- initialize Odd.odd
- initialize Odd.b by calling Even.even
- error: Even.even is not yet initialized

So semantics (a) makes it more possible to make a cyclic dependency work, but 
it's still subtle if you're trying to let them refer to each other in top-level 
initialization code: you have to make sure to carefully place the imports late 
enough that the relevant pieces of each modules will have adequately 
initialized.

> jjb ... eager to see modules happen!

Me too! :)

Dave

_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to