A few more module questions
Responding to a few of these:
On Mon, Apr 4, 2011 at 12:33 PM, Axel Rauschmayer <axel at rauschma.de> wrote:
- I think Python uses directories for namespace nesting, which has some pros and cons compared to completely abstracting the file system structure.
It's necessary to completely abstract the file-system structure, since one of the primary use cases doesn't have a file system -- the web. We don't want to bring server-side assumptions to the web.
Renaming:
- I find this syntax slightly unintuitive: import Geometry.{draw: drawShape} At first glance this would mean for me: rename drawShape to draw. "draw" feels to me like the result of the import.
This is based on the destructuring syntax, where this:
let {draw: drawShape} = ... some expression ...;
also binds the identifier |drawShape|.
- Possible alternative: import Geometry.{draw <- drawShape} (maybe a colon is not a good choice here)
We want to keep this as close as possible to other syntactic constructs in the language.
Renaming:
- I find this syntax slightly unintuitive: import Geometry.{draw: drawShape} At first glance this would mean for me: rename drawShape to draw. "draw" feels to me like the result of the import.
This is based on the destructuring syntax, where this:
let {draw: drawShape} = ... some expression ...;
also binds the identifier |drawShape|.
Got it. Makes sense.
On 2011-04-04, at 12:40, Sam Tobin-Hochstadt wrote:
Renaming:
- I find this syntax slightly unintuitive: import Geometry.{draw: drawShape} At first glance this would mean for me: rename drawShape to draw. "draw" feels to me like the result of the import.
This is based on the destructuring syntax, where this:
let {draw: drawShape} = ... some expression ...;
also binds the identifier |drawShape|.
FWIW, I read these destructuring patterns backwards too. Must be a left/right brain thing. Something I will have to learn the hard way to make it stick.
The way I think about it is, whenever you have X: Y where X and Y are identifiers, the one on the left is fixed and the one on the right is variable.
-
In an object literal, the one on the left is a symbolic property name and the one on the right is a variable.
-
In destructuring, the one on the left is the fixed name of the property you're destructuring and the one on the right is the variable name you're locally binding.
-
In module importing, the one on the left is the fixed name of the foreign export you're importing, and the one on the right is the variable name you're locally binding.
Right. In this case, pattern matching object literals is a good metaphor, assignment (lhs is "new", rhs is "old") isn't.
- Does it ever make sense to access globals via "this"? If so, I assume there will be a use case in the upcoming modules rationale document.
Reflecting the globals via |this| preserves some web compatibility with programs that dynamically test the global object. It allows you some lightweight reflection of the global scope, while removing some of the more problematic reflection of legacy JS (such as deleting globals). For example, you can dynamically detect whether a variable is bound.
- Should there be a keyword for "the current module" (a module-this, if you will)? Accessing module-global data via "this" feels strange (I that is indeed the intention of what I have read). It would also not work inside methods.
I don't know why it feels strange to you; it feels pretty natural to me. Banning |this| in certain contexts has never been done in JS and I don't want to start doing it. If we don't ban it, it has to have some binding. Binding it to null or undefined would also be draconian.
When modules are reflected as first-class values, they are represented as objects. The body of a module acts as the object's constructor. Binding the module object as |this| fits naturally with the design.
But it seems like the only globals inside a module are module-relative. Then everything would work out fine.
I don't understand this comment.
Maybe I was over-thinking this problem: I was wondering how to access module-global data if "this" is shaded. It seemed similar to the "var self = this" work-around when using non-methods inside methods (forEach() etc.).
module Foo { var bar = "abc"; // like a global inside this module, right? export var Baz = { amethod: { // how to access bar here? As a global? "this" won't work. } } }
This would become more complicated with nested modules.
Yes, |this| is shadowed as it is in functions. You could always do |var self = this| if you want:
module M {
var self = M;
module N {
... self ...
}
}
but modules are already named, so you can just use the name instead:
module M {
module N {
... M ...
}
}
On Apr 4, 2011, at 9:51 AM, P T Withington wrote:
On 2011-04-04, at 12:40, Sam Tobin-Hochstadt wrote:
Renaming:
- I find this syntax slightly unintuitive: import Geometry.{draw: drawShape} At first glance this would mean for me: rename drawShape to draw. "draw" feels to me like the result of the import.
This is based on the destructuring syntax, where this:
let {draw: drawShape} = ... some expression ...;
also binds the identifier |drawShape|.
FWIW, I read these destructuring patterns backwards too. Must be a left/right brain thing. Something I will have to learn the hard way to make it stick.
This does happen, but there's no way to "fix" it for you mano sinestro types ;-). The property identifier must be a compile-time constant and on the left of :, so the variable name into which to destructure is on the right of :.
Fortunately there's a short-hand:
let {draw, move} = GraphixAPIObject;
where the property id also names the variable to bind.
It has been proposed that this shorthand be supported for structuring as well as destructuring:
saveObject({draw, move});
would pass a new Object created as if by the initialiser ({draw: draw, move: move}). The property id is treated as an identifier expression and evaluated to get the property value.
We have some support for this
I like it. Useful, with little conceptual and syntactical baggage.
On Thu, Apr 7, 2011 at 12:20, Brendan Eich <brendan at mozilla.com> wrote:
Fortunately there's a short-hand:
let {draw, move} = GraphixAPIObject;
Given this, is there any reason for anything but "import ModuleName.*" then?
Yes. The RHS of a let binding is a dynamic expression, and involves no static checking. The RHS of an import is a static module expression with validation -- it checks that the thing you're importing exists, and also prevents you from importing the same name multiple times.
For example:
module M { export var foo = 42 }
let { bar } = M; // dynamic error, not statically caught
vs
module M { export var foo = 42 }
import M.bar; // static error
And also:
module M { export var foo = 42 }
module N { export var foo = "foo" }
let { foo } = M;
let { foo } = N; // either shadows or reassigns, no error
vs
module M { export var foo = 42 }
module N { export var foo = "foo" }
import M.foo;
import N.foo; // static error
Binding "this":
Nesting modules:
Renaming:
FWIW: I’ve tried to summarize the current proposal here, to give JavaScripters a first impression: www.2ality.com/2011/03/first-look-at-upcoming-javascript.html