Namespaces as Sugar (was: complexity tax)
On May 26, 2008, at 10:02 AM, Mark S. Miller wrote:
we could just have these expand into non-identifier strings consisting of components (typically identifiers) separated by some kind of path separator string. The most logical choices for path separator would probably be either "::" or ".".
This is not backward compatible, since code today is free to use such
substrings in property names, and I will be you a donut real code
does use arbitrary printable ASCII strings. BTW, this name-mangling
idea already came up over a year ago:
doku.php? id=meetings:minutes_apr_18_2007#es_3.1_discussion
Then there is the missing open namespaces idea. Without the ability
to implicitly qualify identifiers by namespaces, users (as in XML
with namespaces) have to compose identifiers from different
namespaces using explicit qualifiers on every reference. This is
verbose, tedious, and error-prone, and experience from XML suggests
strongly that it's not sufficiently usable compared to alternatives
that have a single namespace, or that support unqualified imports:
osteele.com/archives/2004/07/a-fresh-canvas, osteele.com/archives/2004/08/unqualified-imports-for-xml, osteele.com/archives/2004/08/unqualified-imports-for-xml
A single namespace does not scale, we know this from today's
situation on the web where, by convention, libraries share a top-
level namespace and put their local names in a single object per
library (MochiKit, dojo, etc.). This leaves unqualified import as the
remaining alternative for usability.
In short, reinventing namespaces via name mangling loses backward
compatibility, and without what Steele calls unqualified import, it
lacks the usability programmers expect from most other languages with
namespaces. Users have to cope in exactly this way today using JS1
(lack of . notation and quote requirements are not the main issue).
Why not give them both better syntax and better semantics?
On Mon, May 26, 2008 at 10:22 AM, Brendan Eich <brendan at mozilla.org> wrote:
Why not give them both better syntax and better semantics?
A wonderful idea! I eagerly await such a proposal.
On May 26, 2008, at 10:34 AM, Mark S. Miller wrote:
On Mon, May 26, 2008 at 10:22 AM, Brendan Eich
<brendan at mozilla.org> wrote:Why not give them both better syntax and better semantics?
A wonderful idea! I eagerly await such a proposal.
Was that mere snarkiness?
The ES4 proposal has unqualified import. It has backward
compatibility in the sense that it does not change the interpretation
of obj["ns::prop"] or obj["ns/prop"]. If it has other problems (it
surely does -- we're working on specifying it fully, and implementing
it in the RI -- both of which help find problems), then please point
them out. Or make an alternative proposal. All I am suggesting is
that any solution (a) not reinterpret existing property names, and
(b) support unqualified import in osteele's sense of the phrase.
On Mon, May 26, 2008 at 11:29 AM, Brendan Eich <brendan at mozilla.org> wrote:
On May 26, 2008, at 10:34 AM, Mark S. Miller wrote:
On Mon, May 26, 2008 at 10:22 AM, Brendan Eich <brendan at mozilla.org> wrote:
Why not give them both better syntax and better semantics? A wonderful idea! I eagerly await such a proposal. Was that mere snarkiness?
It was a snarky answer to what I perceived to be a snarky question. Of course we want "better". The whole argument is about which direction is better. Your question assumes your conclusion.
If I misunderstood your question, and if it actually wasn't snarky, then I apologize and withdraw the snarkiness of my answer.
The ES4 proposal has unqualified import. It has backward compatibility in the sense that it does not change the interpretation of obj["ns::prop"] or obj["ns/prop"].
Depends what you mean by "change the interpretation". IIUC, ES4 would change the interpretation of the second of these to obj[public::"ns/prop"] (or it would if string literals were allowed to the right of a colon). Namespaces-as-Sugar doesn't expand the set of mentionable property names, but it allows some to be said in a syntactically more convenient fashion. This doesn't change the meaning of obj["ns/prop"]. It just allows the syntax obj.ns::prop to mean the same thing.
If it has other problems (it surely does -- we're working on specifying it fully, and implementing it in the RI -- both of which help find problems), then please point them out.
Section 4.7 "Name Resolution" of the draft spec document goes on for nine pages. Do you consider this a problem?
Or make an alternative proposal. All I am suggesting is that any solution (a) not reinterpret existing property names, and (b) support unqualified import in osteele's sense of the phrase.
Earlier I said
So, although I don't find any of these use-cases compelling, I'd agree that #b is at least a real problem, and is the most plausible of the arguments for some additional support in a future JavaScript. My next message, if I get to it, will be "Namespaces as Sugar". If you agree with me that #b is better avoided than solved, feel free to skip it.
so I hope I've been clear that my favorite alternate proposal is to avoid adding any namespace mechanism to EcmaScript at all. This would clearly satisfy your (a) request above. Depending on what "reinterpret" means, I argue that Namespaces-as-Sugar also satisfies (a). It just provides some conveniences for saying what can already be said more awkwardly.
As for your (b), I fail to see why it's good. Remember, we are talking about property names here, not module linkage! What's the compelling need for a single object to simultaneously have properties defined in different namespaces? How would those properties come to be added to that object? I just don't get it. Am I missing something?
On May 26, 2008, at 12:05 PM, Mark S. Miller wrote:
On Mon, May 26, 2008 at 11:29 AM, Brendan Eich
<brendan at mozilla.org> wrote:On May 26, 2008, at 10:34 AM, Mark S. Miller wrote:
On Mon, May 26, 2008 at 10:22 AM, Brendan Eich <brendan at mozilla.org> wrote:
Why not give them both better syntax and better semantics? A wonderful idea! I eagerly await such a proposal. Was that mere snarkiness?
It was a snarky answer to what I perceived to be a snarky question. Of course we want "better". The whole argument is about which direction is better. Your question assumes your conclusion.
Not quite. My point was not snarky, and it did not assume a
conclusion -- it questioned your premise: "Rather than invent new
semantic concepts ...". You propose new syntax that desugars to
existing semantics. I am asking: is there a non-trivial benefit in
extending semantics too? Why not extend semantics too?
The answer turns, I think, on usability of namespaces, in particular
on whether "unqualified import" is important.
It may be hard to argue about usability except by pointing to other
languages. Hence my references to XML namespaces, which pretty
clearly suffer from lack of unqualified import.
It may be that you and I differ again in preferring ES3.1 vs. ES4
premises, and one of the ES4 premises you reject is "unqualified
import is important for usability" (assuming premises justifying
adding namespaces in the first place).
In that case, it would still help if you had an argument based on ES4
premises that led to a simpler ES4. But it would be sillly to repeat
ES3 premises as disqualifying a part of ES4, since they're different
evolutions of ES3 with different design goals based on different
premises.
If I misunderstood your question, and if it actually wasn't snarky, then I apologize and withdraw the snarkiness of my answer.
Thanks.
The ES4 proposal has unqualified import. It has backward
compatibility in the sense that it does not change the interpretation of obj ["ns::prop"] or obj["ns/prop"].Depends what you mean by "change the interpretation". IIUC, ES4 would change the interpretation of the second of these to obj[public::"ns/prop"] (or it would if string literals were allowed to the right of a colon).
It would be something like obj.public::["ns/prop"], but the point is
that this ES4 spelling makes no change from ES3 terms (obj["ns/
prop"]), where every property specified by ES3 or created by an ES3
programmer is in the public (compatibility) namespace. It's
equivalent syntax, it parses to the same post-definition-phase AST node.
Namespaces-as-Sugar doesn't expand the set of mentionable property names, but it allows some to be said in a syntactically more convenient fashion. This doesn't change the meaning of obj["ns/prop"]. It just allows the syntax obj.ns::prop to mean the same thing.
Oh, I see. Two issues apart from usability:
-
Is it compatible with all relevant Ecma standards? It is not with
ECMA-357, E4X. Breaking compatibility with another Ecma standard, one
implemented in at least three common implementations (SpiderMonkey,
Rhino, ActionScript 3 in Flash 9 and higher), may be a cost worth
paying. I'm not convinced, and Ecma/ISO folks may frown on such an
overt incompatibility. -
Is it compatible or safe (integrity-wise) if you allow unqualified
import? Once you allow the identifier expression prop to denote
obj.ns::prop in some ns-importing context where obj is on the scope
chain, it seems to me you've allowed arbitrary ES3 code to inject
identifiers into ES4 namespaces. Consider the case where obj is the
global object.
In ES4, a namespace (a first class object) can be hidden, internal to
a compilation unit (file or script source). It is therefore not
possible in ES4/ES3 mixed embeddings for ES3 to inject names into any
old namespace, just by prefixing "ns/" to the property identifier.
This is an important integrity property.
If it has other problems (it surely does -- we're working on specifying it fully, and implementing it in the RI -- both of
which help find problems), then please point them out.Section 4.7 "Name Resolution" of the draft spec document goes on for nine pages. Do you consider this a problem?
I already replied in an earlier thread: "I agree with you that
namespaces add more complexity than classes alone".
But for the record, no: high (or merely moderate) draft-spec page
counts do not constitute a problem by themselves. In particular, a
finished language spec may need many pages to specify something
subtle, which has the beneficial effect of reducing programmer
burden, including cognitive load or "complexity." Someone has to pay
for a solution to a problem such as namespacing. There's no free
lunch. Currently ES puts almost all the burden on the programmer.
Also, the spec draft pages currently dedicated to name lookup seem to
me ripe for reduction in size. Maybe not to one page, but we'll see.
It's too early, besides being inconclusive, to bean-count spec pages
and score accordingly.
As for your (b), I fail to see why it's good. Remember, we are talking about property names here, not module linkage!
Who said anything about modules? Oliver Steele's "import" usage
should not mislead. We're talking about how to use namespaces without
requiring every reference to a namespace-qualified name to be
explicitly prefixed by a qualifier. Namespaces cut across compilation
unit, class, and object boundaries in ES4 as proposed.
What's the compelling need for a single object to simultaneously have properties defined in different namespaces? How would those properties come to be added to that object? I just don't get it. Am I missing something?
There are many use-cases. Consider the ES4 spec and Reference
Implementation, which segregate helper and informative methods from
normative ones in the public namespace in the built-in classes. The
Flex framework written in AS3 uses namespaces extensively. C++
programmers use a different but related kind of namespace all the time.
Waldemar's original proposal had namespaces as a cross-cutting
versioning tool:
www.mozilla.org/js/language/old-js2/js20/rationale versioning.html
is worth a read if you haven't looked at his entire original proposal
(he mailed a tarball out recently).
Perhaps more important than any of this, the existing practice among
JS (Ajax) libraries uses namespaces, but allows unqualified import in
various ways to populate more properties of the importing scope
object with shorthands. With this optional importing comes greater
risk of name collision. But it sure looks a lot like ES4's 'use
namespace MochiKit' or 'use namespace dojo'. It looks like
unqualified import.
On Mon, May 26, 2008 at 2:45 PM, Brendan Eich <brendan at mozilla.org> wrote:
In that case, it would still help if you had an argument based on ES4 premises that led to a simpler ES4. But it would be sillly to repeat ES3 premises as disqualifying a part of ES4, since they're different evolutions of ES3 with different design goals based on different premises.
I find this sudden discussion of premises bizarre. In any case, if you'll recall how we got here:
On Mon, May 19, 2008 at 4:32 PM, Douglas Crockford <douglas at crockford.com> wrote:
These essential features will be added without resorting to new syntax.
On Mon, May 19, 2008 at 4:46 PM, Brendan Eich <brendan at mozilla.org> wrote:
New syntax is what's needed to make these usable.
On Mon, May 19, 2008 at 6:54 PM, Mark Miller <erights at gmail.com> wrote:
I agree that it would be nice to have better syntactic conveniences for some of these features. I also agree that the ES4 syntax has some decent conveniences. Given the inescapable legacy compatibility constraints, it's amazing how well they turned out; kudos! If I could have a language with some of the syntactic conveniences of ES4 but without ES4's semantics, I'd be quite happy.
2008/5/19 Brendan Eich <brendan at mozilla.org>:
What semantics in particular, can you pick on something specific that's not in your classes as sugar proposal (rather than have me guess)? BTW, since you missed the cuts in the spreadsheet, you may have missed the optional type checker being cut too: 'use strict' is good-taste mode, a la Perl and in accord with discussions we've had at the last two TC39 meetings. Thanks for the kind words, although since neither 3.1 nor 4 is done yet, specific constructive criticism is even better.
That is a reasonable request which I appreciate. I am attempting to do so, rather than argue from supposed ES4 premises.
On Mon, May 19, 2008 at 6:54 PM, Mark Miller <erights at gmail.com> wrote:
From prior discussions, I don't believe it's possible to find something in the middle that we can all agree on -- though I would still like to!
If the various camps define incompatible positions as premises, then we may as well give up all hope of agreeing on very much. But a wise person once said something like
In mathematics, we justify theorems by derivation from axioms. But as mathematicians, we judge axioms based on what theorems they produce.
(I think it may have been Karl Popper, but I have been unable to find anything by searching. Any pointers would be appreciated.)
Rather than proceeding from premises, let's continue to argue about goals, tradeoffs and taste. Despite everything, I remain hopeful that we may find ourselves agreeing on more than the current state of the argument would suggest. From your reasonable request, and from your citing the history of cuts to date, I hoped you felt likewise. I hope you still do.
On May 26, 2008, at 6:53 PM, Mark S. Miller wrote:
On Mon, May 26, 2008 at 2:45 PM, Brendan Eich <brendan at mozilla.org>
wrote:In that case, it would still help if you had an argument based on ES4 premises that led to a simpler ES4. But it would be sillly to
repeat ES3 premises as disqualifying a part of ES4, since they're different
evolutions of ES3 with different design goals based on different premises.I find this sudden discussion of premises bizarre.
Bizarre or not, it's apparently necessary, since you accused me of
assuming a conclusion, when I was questioning a premise.
Demonstrating my counter-claim required some statement of that premise.
I then thought to allow as how it's not shared by ES3.1, but I really
don't know. ES3.1 has no notion of namespace. This spun-out thread
"Namespaces as Sugar" might be a proposal aimed at 3.1 that's mean to
show no need for ES4's namespace semantics, but it does not address
the "unqualified import" use-case, which requires new semantics in
ES4 not in ES3 or ES3.1. We need to agree or disagree that this use-
case matters enough to justify the extra semantics.
I hope it's clear now why I'm breaking down premises, beyond
demurring from your assertion that I assumed a conclusion. I'm still
waiting to hear you reject as unnecessary the unqualified import
facility, which is found in many languages -- and not just in their
module systems.
In any case, if you'll recall how we got here:
I recall well, but thanks for diagramming most (but not all!) of the
thread.
On Mon, May 19, 2008 at 4:32 PM, Douglas Crockford <douglas at crockford.com> wrote:
These essential features will be added without resorting to new syntax.
Context is missing here. Why? "These" is a pronoun referring not to
namespaces, but to other features missing from ES3. Here's the
context you omitted:
Brendan Eich wrote:
On Mar 26, 2008, at 10:01 AM, Ric Johnson wrote:
Let us take action instead of throwing opinions around: Brendan: What new features that can not be implemented via code constructs now?
This is reductionism, therefore between silly and wrong, but I will
list a few things:
- you can't make read-only properties in ES3;
*you can't make don't-delete properties of plain old objects (only
vars in closures);
you can't make objects that cannot be extended;
you can't make don't-enum properties in plain old objects;
Doug then replied:
It looks like these omissions will be corrected in ES3.1 by the Object.defineProperties function. These essential features will be
added without resorting to new syntax.
which links up to the first line you quoted in the thread ("These
essential features ....").
Where in any of this were namespaces and unqualified import
discussed? Nowhere.
The issues that I argued deserve syntax to be usable may have
semantics in ES3.1 now, so you can argue (and you have, indeed,
argued) for desugaring classes or their fixed properties, e.g. (To
which I counter-argued that desugaring requires a source to source
compiler like GWT, which not everyone should have to use to get the
sugar. But that is another thread that died off.)
But nowhere above in my list to which Doug replied are namespaces to
be found. So new semantics as well as syntax may be needed, depending
on what use-cases we think are important. And I'm arguing that
unqualified-import is important.
If the various camps define incompatible positions as premises, then we may as well give up all hope of agreeing on very much.
A premise can be a conclusion from a prior major premise, plus a
minor premise (or other style of reasoning than syllogistic). I think
you're mixing up axiom and premise here. Aha!
But a wise person once said something like
In mathematics, we justify theorems by derivation from axioms. But as mathematicians, we judge axioms based on what theorems they produce.
(I think it may have been Karl Popper, but I have been unable to find anything by searching. Any pointers would be appreciated.)
Hey, I like Popper too -- but our struggle is not a stand-off between
contradictory axioms, rather it's a search for the axioms (self-
evident propositions) that are the root premises from which we've
both reasoned to other premises, and then to conclusions in the form
of pragmas like "use namespace N".
You switched from "premise" to "axiom" by hauling a Popper quote in,
but premise != axiom, so we are still not engaging at the level of
axioms. ES3.1 and ES4 contain conclusions from derived premises that
are themselves conclusions of prior premises, etc., going back in a
chain of reasoning to axioms.
That's why I keep raising usability as an issue. Without "unqualified
import" (Oliver Steele's phrase) or "use namespace N" in ES4 terms,
experience with other languages leads to the conclusion that
namespaces that must be explicitly qualified on every use are not
usable. That's a premise for the further reasoning that has resulted
in ES4 namespaces, the name lookup algorithm, etc.
Rather than proceeding from premises, let's continue to argue about goals, tradeoffs and taste.
Sorry, those are shifting sands. Let's try to get back toward some
shared premises, if not toward Mathematical axioms, without dying of
boredom from all the fine-grained logic chopping. After all, we are
starting from ES3, and we have lots of experience with programming
languages in the literature to guide us.
We can appeal to good taste too, but I claim it's much more important
to pay attention to experience. Let's leave Popper alone and get very
concrete here. Have you used XML namespaces in compound documents
with lots of names drawn from two or more vocabularies? It hurts!
On May 26, 2008, at 2:45 PM, Brendan Eich wrote:
There are many use-cases. Consider the ES4 spec and Reference
Implementation, which segregate helper and informative methods from
normative ones in the public namespace in the built-in classes. The
Flex framework written in AS3 uses namespaces extensively. C++
programmers use a different but related kind of namespace all the
time.
C++ does not have namespacing of class members, or anything resembling
it as far as I can tell. Namespaces in C++ are only a top-level
construct, as in many other languages. Many good frameworks have been
written in languages that only support top-level namespaces, not
namespacing of properties or data members or whatever is the local
equivalent.
Waldemar's original proposal had namespaces as a cross-cutting
versioning tool:www.mozilla.org/js/language/old-js2/js20/rationale/versioning.html
is worth a read if you haven't looked at his entire original
proposal (he mailed a tarball out recently).Perhaps more important than any of this, the existing practice among
JS (Ajax) libraries uses namespaces, but allows unqualified import
in various ways to populate more properties of the importing scope
object with shorthands. With this optional importing comes greater
risk of name collision. But it sure looks a lot like ES4's 'use
namespace MochiKit' or 'use namespace dojo'. It looks like
unqualified import.
But this is just unqualified import of a top-level namespace, not of
property namespaces, right? I'm not sure property namespacing is as
critical to programming in the large as top-level namespacing.
On May 26, 2008, at 11:30 PM, Maciej Stachowiak wrote:
On May 26, 2008, at 2:45 PM, Brendan Eich wrote:
There are many use-cases. Consider the ES4 spec and Reference
Implementation, which segregate helper and informative methods
from normative ones in the public namespace in the built-in
classes. The Flex framework written in AS3 uses namespaces
extensively. C++ programmers use a different but related kind of
namespace all the time.C++ does not have namespacing of class members, or anything
resembling it as far as I can tell. Namespaces in C++ are only a
top-level construct, as in many other languages. Many good
frameworks have been written in languages that only support top- level namespaces, not namespacing of properties or data members or
whatever is the local equivalent.
All true -- hence "different but related" -- the ability to cut
across definitions with a single namespace in ES4 is a big one. But
the point for this thread is the usability of unqualified import,
which C++ supports and Mark's desugaring sketch does not, even at top
level only.
Perhaps more important than any of this, the existing practice
among JS (Ajax) libraries uses namespaces, but allows unqualified
import in various ways to populate more properties of the
importing scope object with shorthands. With this optional
importing comes greater risk of name collision. But it sure looks
a lot like ES4's 'use namespace MochiKit' or 'use namespace dojo'.
It looks like unqualified import.But this is just unqualified import of a top-level namespace, not
of property namespaces, right?
Right.
I'm not sure property namespacing is as critical to programming in
the large as top-level namespacing.
The top-level in ES is an object containing properties, so there's
not much difference. Class objects, ad-hoc object, and the global
object all benefit from cross-cutting namespaces in ES4, and in
precursors such as AS3. Whether this is worth the cost is for another
thread. Again my point is the importance of unqualified import for
usability.
On May 26, 2008, at 11:39 PM, Brendan Eich wrote:
On May 26, 2008, at 11:30 PM, Maciej Stachowiak wrote:
On May 26, 2008, at 2:45 PM, Brendan Eich wrote:
There are many use-cases. Consider the ES4 spec and Reference
Implementation, which segregate helper and informative methods
from normative ones in the public namespace in the built-in
classes. The Flex framework written in AS3 uses namespaces
extensively. C++ programmers use a different but related kind of
namespace all the time.C++ does not have namespacing of class members, or anything
resembling it as far as I can tell. Namespaces in C++ are only a
top-level construct, as in many other languages. Many good
frameworks have been written in languages that only support top- level namespaces, not namespacing of properties or data members or
whatever is the local equivalent.All true -- hence "different but related" -- the ability to cut
across definitions with a single namespace in ES4 is a big one. But
the point for this thread is the usability of unqualified import,
which C++ supports and Mark's desugaring sketch does not, even at
top level only.
Actually, in this instance you were answering Mark's question: "What's
the compelling need for a single object to simultaneously have
properties defined in different namespaces?" Nothing to do with
unqualified import per se (which I agree is important for top-level
namespaces at least).
One can certainly question the need for any namespacing of object
properties, let alone unqualified import of namespaces for such
purposes.
Perhaps more important than any of this, the existing practice
among JS (Ajax) libraries uses namespaces, but allows unqualified
import in various ways to populate more properties of the
importing scope object with shorthands. With this optional
importing comes greater risk of name collision. But it sure looks
a lot like ES4's 'use namespace MochiKit' or 'use namespace dojo'.
It looks like unqualified import.But this is just unqualified import of a top-level namespace, not
of property namespaces, right?Right.
I'm not sure property namespacing is as critical to programming in
the large as top-level namespacing.The top-level in ES is an object containing properties, so there's
not much difference. Class objects, ad-hoc object, and the global
object all benefit from cross-cutting namespaces in ES4, and in
precursors such as AS3. Whether this is worth the cost is for
another thread. Again my point is the importance of unqualified
import for usability.
Object property lookup need not be the same as scope chain lookup and
it is ok by me if some global properties can only be accessed
unqualified via the scope chain and not by direct global property
access. The fact that the global namespace is also an object is cute
but does not mean namespaces need to generalize beyond the global
scope. For example, global unqualified namespace import could desugar
(logically) into the injection of scope chain items instead of into a
general property lookup mechanism.
, Maciej
On May 27, 2008, at 12:00 AM, Maciej Stachowiak wrote:
Actually, in this instance you were answering Mark's question: "What's the compelling need for a single object to simultaneously have properties defined in different namespaces?"
I wrote "There are many use-cases" and talked about two: name
collision avoidance, unqualified import. In the course of this, I
cited C++. C++ doesn't have "objects as scopes" or "properties", but
if it did, then the top-level could be a single object with
properties in several namespaces. And C++ does support
"properties" (globals) with the same unqualified identifier but
different namespaces -- and C++ does support unqualified import.
So C++ namespaces are not the same as ES4 namespaces -- I never said
they were (more the reverse)! The points, plural, that I was making
(yes, I was going beyond Mark's question -- I'm not a deposed witness
being interrogated here, so excuse me for talking about more than
what was asked) apply to both C++ and ES4.
One can certainly question the need for any namespacing of object properties, let alone unqualified import of namespaces for such purposes.
I hope so. I'd rather have someone question unqualified import than
implicitly dismiss it, which is what seems to be happening.
The top-level in ES is an object containing properties, so there's not much difference. Class objects, ad-hoc object, and the global object all benefit from cross-cutting namespaces in ES4, and in precursors such as AS3. Whether this is worth the cost is for another thread. Again my point is the importance of unqualified import for usability.
Object property lookup need not be the same as scope chain lookup and it is ok by me if some global properties can only be accessed unqualified via the scope chain and not by direct global property access. The fact that the global namespace is also an object is cute
Fundamental to JS, impossible to change in ES3-compatible areas, and
-- here we may disagree -- unwise to turn away from for future
additions to ES3.
but does not mean namespaces need to generalize beyond the global scope. For example, global unqualified namespace import could desugar (logically) into the injection of scope chain items instead of into a general property lookup mechanism.
That's an interesting idea, although we use namespace qualification
along the prototype chain all over the place in ES4, and for what
seem like good reasons.
ES (any version) has objects as scopes, as well as prototypes. It's
hard to keep the gander -- objects below the top level, or on the
prototype chain -- from wanting the same sauce that the goose -- the
global object -- is trying to hog all to itself.
Objects and their properties move around over time, both along the
scope and prototype chains. Real web apps I've studied from a low-
level actually take advantage of the ability to "pun" objects along
both chains (including the global object).
Also, JS hackers often prototype in global code and then push things
down into closures or sub-objects.
Then there is the namespaces-for-versioning idea, which wants to cut
across classes as well as global objects.
I'm not going to belabor the general argument for uniformity that
favors namespaces as qualifiers usable in all objects that can reach
the given namespace by reference (if it's opaque) or use it by name
(if transparent), because it is a generalization. We have many and
specific use-cases in ES4 (intrinsic, iterator, helper, informative
come to mind) for sub-global namespacing. We've generalized, instead
of making ad-hoc or particular and restrictive solutions.
Is the cost too high? I think that depends on how the name lookup
algorithm works on real-world code. AS3 developers have data to
share. Let's get into that.
On May 26, 2008, at 10:19 PM, Brendan Eich wrote:
I then thought to allow as how it's not shared by ES3.1, but I really don't know. ES3.1 has no notion of namespace. This spun-out thread "Namespaces as Sugar" might be a proposal aimed at 3.1 that's meant to show no need for ES4's namespace semantics, but it does not address the "unqualified import" use-case, which requires new semantics in ES4 not in ES3 or ES3.1. We need to agree or disagree that this use- case matters enough to justify the extra semantics.
I'm still not sure why namespaces keep coming up for ES3.1. This
started in April 2007, with an idea to treat obj["ns::prop"] as the
same as obj.ns::prop in ES4 -- this makes obj.ns::prop not just a
syntactic shorthand, and it reinterprets ES1-3 property names
incompatibly. See the minutes I cited earlier in this thread.
There was a strong "no new syntax" principle in effect for 3.1 at the
time. Soon enough this idea evolved to allow that some new syntax
might be a good thing, so maybe obj.ns::prop and some kind of first-
class namespace (denoted ns in the example) could be added. Users
targeting all browsers would have to use obj["ns::prop"], but when
ES3-only browsers dropped from servers' user-agent radar, scripts on
those servers could start using obj.ns::prop.
Now it seems you are exploring desugaring part, but not all, of ES4
namespaces to ES3 semantics, with a little sugar and some convention
(or other) for property naming, but no first-class namespace object,
so no internal namespaces -- rather, injection attacks -- and no
unqualified import.
Exploring is fine, don't let me discourage you. I don't mean to
complain. But I hope there's no mission creep going on for ES3.1 that
would try to add primitives (the fewest possible) for every new
facility in ES4 not in ES3.1. That is a good way to delay 3.1 and 4,
and multiple design by committee (if not square it, per Metcalfe's Law).
Keep 3.1 small. That's my motto, and Doug's too I'm sure. Sound right?
On Tue, May 27, 2008 at 12:48 AM, Brendan Eich <brendan at mozilla.org> wrote:
Exploring is fine, don't let me discourage you. I don't mean to complain. But I hope there's no mission creep going on for ES3.1 that would try to add primitives (the fewest possible) for every new facility in ES4 not in ES3.1. That is a good way to delay 3.1 and 4, and multiple design by committee (if not square it, per Metcalfe's Law).
Keep 3.1 small. That's my motto, and Doug's too I'm sure. Sound right?
Yes, agreed. Namespaces-as-Sugar (hereafter NAS) is too big for ES3.1. Perhaps it's too small for ES4. Again, it is simply my attempt to explain what I meant by "A language with some of ES4's syntactic conveniences but without ES4's semantics." I would be less happy with NAS added to a language than with nothing added -- the problem it addresses is a problem more in theory than in practice. The real problem in practice is module linkage. Dojo and YUI show that this is already adequately solved with patterns and libraries, with no new language mechanism needed.
As I stated, I expect the current truce between the camps -- resulting in two successor languages -- is probably the best we can do. It's certainly a lot better than the previous stalemate. But I'm still curious and hopeful whether a "language with some of ES4's syntactic conveniences but without ES4's semantics" might be an intermediate point we could get all around agreement on. Probably not, but it is worth asking.
On May 27, 2008, at 12:33 AM, Brendan Eich wrote:
On May 27, 2008, at 12:00 AM, Maciej Stachowiak wrote:
Actually, in this instance you were answering Mark's question:
"What's the compelling need for a single object to simultaneously have properties defined in different namespaces?"I wrote "There are many use-cases" and talked about two: name
collision avoidance, unqualified import. In the course of this, I
cited C++. C++ doesn't have "objects as scopes" or "properties", but
if it did, then the top-level could be a single object with
properties in several namespaces. And C++ does support
"properties" (globals) with the same unqualified identifier but
different namespaces -- and C++ does support unqualified import.So C++ namespaces are not the same as ES4 namespaces -- I never said
they were (more the reverse)! The points, plural, that I was making
(yes, I was going beyond Mark's question -- I'm not a deposed
witness being interrogated here, so excuse me for talking about more
than what was asked) apply to both C++ and ES4.
I don't see how any of this argues for namespacing of properties on
non-global objects, or why that case in particular requires
unqualified import.
One can certainly question the need for any namespacing of object properties, let alone unqualified import of namespaces for such purposes.
I hope so. I'd rather have someone question unqualified import than
implicitly dismiss it, which is what seems to be happening.
I don't see how your statement is responsive. Namespacing of non-
object properties is poorly justified, in my opinion. Unqualified
import of top-level names is well-justified. I don't see why you keep
mixing the two together.
The top-level in ES is an object containing properties, so there's not much difference. Class objects, ad-hoc object, and the global object all benefit from cross-cutting namespaces in ES4, and in precursors such as AS3. Whether this is worth the cost is for another thread. Again my point is the importance of unqualified import for usability.
Object property lookup need not be the same as scope chain lookup and it is ok by me if some global properties can only be accessed unqualified via the scope chain and not by direct global property access. The fact that the global namespace is also an object is cute
Fundamental to JS, impossible to change in ES3-compatible areas, and
-- here we may disagree -- unwise to turn away from for future
additions to ES3.
I don't disagree, the global object is reified so unlike activations
it cannot be treated as just a convenient spec fiction and nor can it
safely be removed.
but does not mean namespaces need to generalize beyond the global scope. For example, global unqualified namespace import could desugar (logically) into the injection of scope chain items instead of into a general property lookup mechanism.
That's an interesting idea, although we use namespace qualification
along the prototype chain all over the place in ES4, and for what
seem like good reasons.
Other languages with successful namespacing features don't have such a
mechanism, so I am dubious of the goodness of these ideas. I am
concerned that the namespace lookup algorithm for object property
access is too complicated. It makes object property lookup depend on
the set of open namespaces, which means obj.property may compile to
entirely different code depending on the context, and it seems likely
it will slow down property lookup when multiple namespaces are open
but static type info is missing. If the only real justification is
that it's a nice generalization, then I do not think it is worth the
performance hit.
ES (any version) has objects as scopes, as well as prototypes. It's
hard to keep the gander -- objects below the top level, or on the
prototype chain -- from wanting the same sauce that the goose -- the
global object -- is trying to hog all to itself.
Is it really? Is there any other language where namespacing of the
global namespace has led to namespacing at the sub-object level? C++,
Java and Python all get by fine without namespacing of individual
object properties.
The reason namespacing at top level is essential to programming in the
large is that the global namespace is a shared resource and must be
partitioned in controlled ways to avoid collision in a large system.
But I do not see how this argument applies to classes or objects.
Objects and their properties move around over time, both along the
scope and prototype chains. Real web apps I've studied from a low- level actually take advantage of the ability to "pun" objects along
both chains (including the global object).
Nontheless, the global namespace is unique. There's no way to replace
the global object.
Also, JS hackers often prototype in global code and then push things
down into closures or sub-objects.Then there is the namespaces-for-versioning idea, which wants to cut
across classes as well as global objects.I'm not going to belabor the general argument for uniformity that
favors namespaces as qualifiers usable in all objects that can reach
the given namespace by reference (if it's opaque) or use it by name
(if transparent), because it is a generalization. We have many and
specific use-cases in ES4 (intrinsic, iterator, helper, informative
come to mind) for sub-global namespacing. We've generalized, instead
of making ad-hoc or particular and restrictive solutions.
The fact that the generalization seems to be unique to ES4 makes me
dubious of its actual usefulness. If it has a performance cost, then
the generalization seems like a dubious choice.
Is the cost too high? I think that depends on how the name lookup
algorithm works on real-world code. AS3 developers have data to
share. Let's get into that.
I'd love to hear the data. AS3 developers, can unqualified lookup of
object properties on untyped references in the presence of property
namespaces be as fast as when there aren't namespaces at all? If so,
how? The most obvious way to do property lookup when there is no
static type info is a hashtable lookup on each prototype chain entry,
but I do not see an obvious way that a single hashtable lookup can
look in multiple namespaces. I suspect the answer to this in AS3 is
that if you want performance, you have to use type declarations.
, Maciej
On Tue, May 27, 2008 at 07:32, Mark S. Miller <erights at google.com> wrote:
Yes, agreed. Namespaces-as-Sugar (hereafter NAS) is too big for ES3.1. Perhaps it's too small for ES4. Again, it is simply my attempt to explain what I meant by "A language with some of ES4's syntactic conveniences but without ES4's semantics." I would be less happy with NAS added to a language than with nothing added -- the problem it addresses is a problem more in theory than in practice. The real problem in practice is module linkage. Dojo and YUI show that this is already adequately solved with patterns and libraries, with no new language mechanism needed.
This is the second time I hear you say that the namespace pattern used by dojo and YUI is already adequate. Let me debunk that myth. Dojo flattened their namespaces from things like dojo.foo.bar.baz to dojo.baz since the ES3 namespace pattern is too vefrbose and painful to use. YUI people also complain that writing YAHOO.foo is painful (all caps is hard to type).
Unqualified import of global objects is a must for programming at large.
I agree with Maciej here, if we can simplify the name lookup significantly be removing unqualified import of property names then I think we should do that. That being said, having namespaced properties seems useful and I'd rather have that if it can be made to perform well as well as be made simpler to understand.
On May 27, 2008, at 8:45 AM, Maciej Stachowiak wrote:
I don't see how any of this argues for namespacing of properties on
non-global objects, or why that case in particular requires
unqualified import.
The topic was any single object, so if these are good for the global
object, they may (not must) be good for other objects. That's the
general (uniformity) argument, made further below (I'm hoping for a
response).
One can certainly question the need for any namespacing of object properties, let alone unqualified import of namespaces for such purposes.
I hope so. I'd rather have someone question unqualified import
than implicitly dismiss it, which is what seems to be happening.I don't see how your statement is responsive.
Hey, I was agreeing with you (Mr. Assistant District Attorney Sir :- P). Questioning is fine.
What was "responsive" about your non-sequitur "One can certainly
question the need ..." anyway? No one objects to asking clear
questions that are not of the "when did you stop beating your wife"
kind.
What's at issue is whether and why unqualified import matters in any
object, even the global object only, since the NAS proposal did not
allow unqualified import even at global level, and the use-case for
unqualified import was dismissed as not compelling.
Namespacing of non-object properties is poorly justified, in my
opinion. Unqualified import of top-level names is well-justified. I
don't see why you keep mixing the two together.
Sure you do, below where I gave particulars that led to the
generalized namespace scheme in ES4.
but does not mean namespaces need to generalize beyond the global scope. For example, global unqualified namespace import could
desugar (logically) into the injection of scope chain items instead of
into a general property lookup mechanism.That's an interesting idea, although we use namespace
qualification along the prototype chain all over the place in ES4,
and for what seem like good reasons.Other languages with successful namespacing features don't have
such a mechanism, so I am dubious of the goodness of these ideas. I
am concerned that the namespace lookup algorithm for object
property access is too complicated.
Agreed, this is the big issue. I share your concern, but the
conservative approach (esp. with reference to C++) of throwing out
non-global open namespaces looks like an overreaction, and it may not
save much complexity.
It makes object property lookup depend on the set of open
namespaces, which means obj.property may compile to entirely
different code depending on the context,
Lexical context, no dynamic open-namespaces scope.
and it seems likely it will slow down property lookup when multiple
namespaces are open but static type info is missing.
It certainly could, although we think not in implementations under
way. Opening multiple namespaces without is not free in a dynamic
language.
Is the name lookup algorithm much simpler if namespaces are top-level
only? Since obj.prop could end up with obj referring to the (or I
should write "a") global object, I don't see it. Unless you're
proposing outlawing such object references using the namespaces open
at top-level when obj is the global object.
If the only real justification is that it's a nice generalization,
then I do not think it is worth the performance hit.
The nice generalization followed from particular use-cases, it did
not precede them. I cited those cases (briefly). How about being
responsive to them?
ES (any version) has objects as scopes, as well as prototypes.
It's hard to keep the gander -- objects below the top level, or on
the prototype chain -- from wanting the same sauce that the goose
-- the global object -- is trying to hog all to itself.Is it really? Is there any other language where namespacing of the
global namespace has led to namespacing at the sub-object level? C+ +, Java and Python all get by fine without namespacing of
individual object properties.
C++ and Java are not the right paradigms for JS/ES. Python is better,
but Python does allow import in local scope.
The reason namespacing at top level is essential to programming in
the large is that the global namespace is a shared resource and
must be partitioned in controlled ways to avoid collision in a
large system. But I do not see how this argument applies to classes
or objects.
See Mark's big post, which discusses (in item (b)) extending objects,
including standard ones.
Saying the global object is a shared resource that must be
partitioned, etc., but no others reachable from it, particularly
class objects, are shared resources, is begging the question: what
makes any object a shared resource? That the global is the only
necessarily shared object does not reduce the benefit, or make the
cost prohibitive, of sharing other objects reachable from it.
Prototype (the Ajax library) may have erred in extending standard
object prototypes. But if it had namespaces as proposed in ES4, and
control over enumerability, then why not? Then there are non-
prototype standard objects that can be (and are, in JS1/ES3 code
today) shared and extended, with possibly conflicting names.
Anyway, it seems we're beating around the bush still. Responding to
the particular reasons for generalized namespaces would be better
than asserting that the global object is the only shared resource,
simply because it must be shared.
Objects and their properties move around over time, both along the
scope and prototype chains. Real web apps I've studied from a low- level actually take advantage of the ability to "pun" objects
along both chains (including the global object).Nontheless, the global namespace is unique. There's no way to
replace the global object.
You're right, but that does not mean programmers should have to
partition only the global object with namespaces or anything like
them. The global object is the first object to come to mind, but not
the only, and Prototype along with lots of other (library or ad-hoc)
JS code on the web shows the utility of extending non-global objects.
I do not mean to oversell this point, since Ajax hackers have swerved
away from Prototype-like extension. But that swerving is focused on
standard prototypes, especially Object.prototype, and it depends also
on the inability to prevent for-in enumeration. It is not reason for
confining namespacing to the global object, any more than Prototype
is proof that we must allow namespacing at any level in the object
hierarchy.
The arguments so far are not going to make or break namespaces as
proposed, by themselves. Moving along:
Also, JS hackers often prototype in global code and then push
things down into closures or sub-objects.Then there is the namespaces-for-versioning idea, which wants to
cut across classes as well as global objects.I'm not going to belabor the general argument for uniformity that
favors namespaces as qualifiers usable in all objects that can
reach the given namespace by reference (if it's opaque) or use it
by name (if transparent), because it is a generalization. We have
many and specific use-cases in ES4 (intrinsic, iterator, helper,
informative come to mind) for sub-global namespacing. We've
generalized, instead of making ad-hoc or particular and
restrictive solutions.The fact that the generalization seems to be unique to ES4 makes me
dubious of its actual usefulness. If it has a performance cost,
then the generalization seems like a dubious choice.
First, performance is not king or JS would not have prototypes and
dynamic typing. It's not a trump card.
Second (after all the warm-up sparring), you didn't respond to the
particulars that led to the generalization:
- internal namespace per compilation unit for information hiding --
hardcode as a special case? - iterator and meta hooks in objects. Ugly get, etc., names instead?
- helper_foo() and informative_bar() in the RI?
The use of __ brackets is a problem for rewriting systems like Caja.
Whitelisting standard hook names could work, but is this really
the best we can do? I doubt it.
Is the cost too high? I think that depends on how the name lookup
algorithm works on real-world code. AS3 developers have data to
share. Let's get into that.I'd love to hear the data. AS3 developers, can unqualified lookup
of object properties on untyped references in the presence of
property namespaces be as fast as when there aren't namespaces at
all? If so, how? The most obvious way to do property lookup when
there is no static type info is a hashtable lookup on each
prototype chain entry, but I do not see an obvious way that a
single hashtable lookup can look in multiple namespaces.
Competitively optimizing JS, excluding namespaces, increasingly
requires non-obvious implementation techniques.
This is a good trade-off if it can be done in reasonable footprint,
since there is a huge installed base, and a pretty-big knowledge
base. We're not, for example, going to remove the ability to replace
String.prototype.charAt, in any compatible ESn version.
Optimization ease is not and should not be the sole consideration.
Exotic techniques should not be mandated by the spec, on the other
hand. But without 'use namespace N' pragmas, programmers will not run
into ambiguities at compile time, that result in run-time cost.
Programmers can buy by the yard here, as with other parts of the
language that trade performance (or alternatively: that fuel demand
for more optimized runtimes) in exchange for expressiveness. And for
a lot of JS code, core language performance does not matter even if
you go nuts with eval and 'with', compared to other costs dominating
the critical paths.
I suspect the answer to this in AS3 is that if you want
performance, you have to use type declarations.
That may be the case for AS3 code using Flex, but even such a result
would be informative -- don't open multiple namespaces if you're
using untyped objects and targeting an unoptimized implementation.
But really, why is any of the several feature combinations that could
hurt performance (with, eval, deep scope chains and prototype chains
in most implementations) a reason to cripple the language?
Performance is not king, and JS ain't C++.
On May 27, 2008, at 11:00 AM, Brendan Eich wrote:
What's at issue is whether and why unqualified import matters in any
object, even the global object only, since the NAS proposal did not
allow unqualified import even at global level, and the use-case for
unqualified import was dismissed as not compelling.
There's really 4 separable issues:
- Namespacing of names at global scope (via lexically scoped
reference). - Unqualified import of names into global scope.
- Namespacing of arbitrary object properties.
- Unqualified import of namespaces for arbitrary object properties.
I would claim 1 and 2 are essential, 3 can be done by convention in
the absence of 4 (a la the NAS proposal) and 4 is unnecessary and
harmful to performance.
That's an interesting idea, although we use namespace
qualification along the prototype chain all over the place in ES4,
and for what seem like good reasons.Other languages with successful namespacing features don't have
such a mechanism, so I am dubious of the goodness of these ideas. I
am concerned that the namespace lookup algorithm for object
property access is too complicated.Agreed, this is the big issue. I share your concern, but the
conservative approach (esp. with reference to C++) of throwing out
non-global open namespaces looks like an overreaction, and it may
not save much complexity.
It could save a lot of complexity, by not requiring any first-class
support for namespace lookup on arbitrary objects.
It makes object property lookup depend on the set of open
namespaces, which means obj.property may compile to entirely
different code depending on the context,Lexical context, no dynamic open-namespaces scope.
Note I said "compile to" so I think this was clear.
and it seems likely it will slow down property lookup when multiple
namespaces are open but static type info is missing.It certainly could, although we think not in implementations under
way. Opening multiple namespaces without is not free in a dynamic
language.Is the name lookup algorithm much simpler if namespaces are top- level only? Since obj.prop could end up with obj referring to the
(or I should write "a") global object, I don't see it. Unless you're
proposing outlawing such object references using the namespaces open
at top-level when obj is the global object.
I would propose that unqualified import only affects lexically scoped
lookups, not object property access, even if the object in question is
the global object. In particular, if you are willing to say
"global.property" instead of "property", it is not such a hardship to
say "global.ns::property".
If the only real justification is that it's a nice generalization,
then I do not think it is worth the performance hit.The nice generalization followed from particular use-cases, it did
not precede them. I cited those cases (briefly). How about being
responsive to them?
I think many (perhaps all) of those cases either use namespaces
gratuitously or work fine without unqualified import (and so could use
namespaces by convention). For example it doesn't seem important to
allow unqualified import of the meta namespace.
ES (any version) has objects as scopes, as well as prototypes.
It's hard to keep the gander -- objects below the top level, or on
the prototype chain -- from wanting the same sauce that the goose
-- the global object -- is trying to hog all to itself.Is it really? Is there any other language where namespacing of the
global namespace has led to namespacing at the sub-object level? C+ +, Java and Python all get by fine without namespacing of
individual object properties.C++ and Java are not the right paradigms for JS/ES. Python is
better, but Python does allow import in local scope.
Python allows import from inside a local namespace, but does it allow
import from outside a local namespace to affect lookup into that
namespace? I am not aware of such a feature but I'm not a Python expert.
The reason namespacing at top level is essential to programming in
the large is that the global namespace is a shared resource and
must be partitioned in controlled ways to avoid collision in a
large system. But I do not see how this argument applies to classes
or objects.See Mark's big post, which discusses (in item (b)) extending
objects, including standard ones.Saying the global object is a shared resource that must be
partitioned, etc., but no others reachable from it, particularly
class objects, are shared resources, is begging the question: what
makes any object a shared resource? That the global is the only
necessarily shared object does not reduce the benefit, or make the
cost prohibitive, of sharing other objects reachable from it.
The benefit is less, because you can use separate objects in different
namespaces instead of a shared object with namespaces inside it. The
cost is greater because it makes all property lookup more expensive.
The fact that the generalization seems to be unique to ES4 makes me
dubious of its actual usefulness. If it has a performance cost,
then the generalization seems like a dubious choice.First, performance is not king or JS would not have prototypes and
dynamic typing. It's not a trump card.
JS does have many features that are not good for performance. But that
does not mean we should add more.
Second (after all the warm-up sparring), you didn't respond to the
particulars that led to the generalization:
- internal namespace per compilation unit for information hiding --
hardcode as a special case?
I'm not sure how this applies to unqualified import of namespaces on
arbitrary object properties.
- iterator and meta hooks in objects. Ugly get, etc., names
instead?
Unqualified import is not necessary for iterator or meta hooks.
Namespaces by convention (or decoratedNames) would be enough.
- helper_foo() and informative_bar() in the RI?
I don't think any language feature should exist solely for the
convenience of the RI.
The use of __ brackets is a problem for rewriting systems like Caja.
Whitelisting standard hook names could work, but is this really
the best we can do? I doubt it.Is the cost too high? I think that depends on how the name lookup
algorithm works on real-world code. AS3 developers have data to
share. Let's get into that.I'd love to hear the data. AS3 developers, can unqualified lookup
of object properties on untyped references in the presence of
property namespaces be as fast as when there aren't namespaces at
all? If so, how? The most obvious way to do property lookup when
there is no static type info is a hashtable lookup on each
prototype chain entry, but I do not see an obvious way that a
single hashtable lookup can look in multiple namespaces.Competitively optimizing JS, excluding namespaces, increasingly
requires non-obvious implementation techniques.
For that very reason, it is a very bad idea to add features that
intrinsically require non-obvious implementation techniques to get
decent performance. If more effort must be spent the necessary
complexity of the language just to preserve current levels of
performance, then that takes away resources from implementing
unnecessary complexity to improve performance beyond current levels.
In general, keeping the language simpler is good for performance.
Other things being equal, simpler implementations are easier to
change, and have more room to add complexity for optimization without
becoming too complex for human understanding.
I will agree that some added language features are essential but I
think minor improvements in expressiveness that have large complexity
cost are a poor tradeoff.
This is a good trade-off if it can be done in reasonable footprint,
since there is a huge installed base, and a pretty-big knowledge
base. We're not, for example, going to remove the ability to replace
String.prototype.charAt, in any compatible ESn version.
Preserving compatibility with existing performance-harming features is
not the same thing as introducing new ones.
Optimization ease is not and should not be the sole consideration.
Exotic techniques should not be mandated by the spec, on the other
hand. But without 'use namespace N' pragmas, programmers will not
run into ambiguities at compile time, that result in run-time cost.Programmers can buy by the yard here, as with other parts of the
language that trade performance (or alternatively: that fuel demand
for more optimized runtimes) in exchange for expressiveness. And for
a lot of JS code, core language performance does not matter even if
you go nuts with eval and 'with', compared to other costs dominating
the critical paths.
Programmers have found ways to live with today's performance, and it
is true that for some applications core language performance is not
the bottleneck. But that doesn't mean we can feel free to ignore
performance considerations in the design of new language features.
I suspect the answer to this in AS3 is that if you want
performance, you have to use type declarations.That may be the case for AS3 code using Flex, but even such a result
would be informative -- don't open multiple namespaces if you're
using untyped objects and targeting an unoptimized implementation.But really, why is any of the several feature combinations that
could hurt performance (with, eval, deep scope chains and prototype
chains in most implementations) a reason to cripple the language?
Performance is not king, and JS ain't C++.
Is removing unqualified import of namespaces at non-global scope (the
only aspect of namespaces that seems prima facie harmful to
performance) really "crippling the language"?
, Maciej
2008/5/27 Maciej Stachowiak <mjs at apple.com>:
It could save a lot of complexity, by not requiring any first-class support for namespace lookup on arbitrary objects.
Is the expectation then that having two lookup models, one for global objects and the other for non-global objects, going to provide less complexity?
In a browser, "window" is the global object; would property lookup on "window" be namespaced when referenced as such? When you have a handle to another window? When you use |this.prop| in a global function?
If we have namespace-aware lookup, it seems to me that it would be less complex for implementors and script authors alike for it to always apply, rather than just for one magical object.
Mike
Delurk to ask a question --
On Tue, May 27, 2008 at 12:18 PM, Mike Shaver <mike.shaver at gmail.com> wrote:
In a browser, "window" is the global object; would property lookup on "window" be namespaced when referenced as such? When you have a handle to another window? When you use |this.prop| in a global function?
What is wrong with the following strawman syntax: Define a form --
import into <target> values <namespace>;
which puts all the values <namespace>.* into <target>. This can be
explained in terms of two first class objects, <target> and <namespace>. Now the global case is just a matter of defining an alias
for the global <target>, in case it is not mentionable by a given JS
environment. Like maybe --
import values <namespace>;
The remainder of the asymmetry, where the global lexical scope is addressable as an object yet nested scopes are not mentionable as first-class objects, is endemic to JavaScript and perhaps not a valid topic of debate or change at this point.
This seems to solve the problem for module linkage, yet does not introduce complexities in general purpose object key lookup. It can be modeled simply as an addition of (possibly "virtual") keys to an object. And it (correctly) requires the client to have write access to the <target>.
The problem occurs if you wish to fail "late" in case two namespaces define the same name. This is where the keys can be virtualized so that, at lookup time, an error occurs if a name is ambiguous. Yet this is still localized to one first-class object resolving string keys to first-class object values, which is well within the simple programmer model of existing JS.
Ihab
On May 27, 2008, at 11:42 AM, Maciej Stachowiak wrote:
On May 27, 2008, at 11:00 AM, Brendan Eich wrote:
What's at issue is whether and why unqualified import matters in
any object, even the global object only, since the NAS proposal
did not allow unqualified import even at global level, and the use- case for unqualified import was dismissed as not compelling.There's really 4 separable issues:
- Namespacing of names at global scope (via lexically scoped
reference).- Unqualified import of names into global scope.
- Namespacing of arbitrary object properties.
- Unqualified import of namespaces for arbitrary object properties.
I would claim 1 and 2 are essential, 3 can be done by convention in
the absence of 4 (a la the NAS proposal) and 4 is unnecessary and
harmful to performance.
Thanks, this is helpful, since the argument you joined was about (2)
and/or (4) -- there is no unqualified import in the NAS sketch.
I forgot one of the main use-case for 4, one you've expressed
interest in already: 'use namespace intrinsic'. Without (4), this
does not allow early binding for s.charAt(i) given var s:string to
string.prototype.intrinsic::charAt. So you can't add one pragma and
realize speedups or better type signatures for built-in methods. All
you can do is access global intrinsic::foo bindings, which (in ES4,
where opt-in versioning gets you immutable Object, Array, String,
etc. without needing to open intrinsic) are few and not likely to
realize a speed-up or more precise typing.
So early binding via namespacing would be gone. It could be
reintroduced via an ad-hoc pragma. But that takes up complexity
budget in the spec and real implementations too.
It could save a lot of complexity, by not requiring any first-class
support for namespace lookup on arbitrary objects.
If I understand your proposal, meta::get or iterator::get could still
be defined in an arbitrary object, and called with full qualification.
Lexical context, no dynamic open-namespaces scope.
Note I said "compile to" so I think this was clear.
Just dotting an i, especially for everyone following along at home :-).
- internal namespace per compilation unit for information hiding
-- hardcode as a special case?I'm not sure how this applies to unqualified import of namespaces
on arbitrary object properties.
Per the spec, internal is open in a separate set on the list of open
namespaces. You don't have to qualify references to internal::foo.
- iterator and meta hooks in objects. Ugly get, etc., names
instead?Unqualified import is not necessary for iterator or meta hooks.
Namespaces by convention (or decoratedNames) would be enough.
Agreed :-).
- helper_foo() and informative_bar() in the RI?
I don't think any language feature should exist solely for the
convenience of the RI.
It's not just the RI. Namespacing for informative purposes in the RI
is good programming style, akin to using helper namespaces in C++
where top-level (but often class-level as you can see from reading RI
builtins/*.es). grep 'use namespace ' builtins/*.es
runs to 41 lines.
If more effort must be spent the necessary complexity of the
language just to preserve current levels of performance,
No, to increase the levels of performance for the current version of
the language. That's the horse going over the first hill from the barn.
Adding namespaces to the next major version could slip into the
optimization frameworks under way in a couple of engines I know of.
But you may doubt. That's ok. I maintain that the high order bit
should not be the cost to implementors, rather utility vs. complexity
facing users.
then that takes away resources from implementing unnecessary
complexity to improve performance beyond current levels.
Or harmonizes with the "unnecessary" complexity that implementors
trying to compete already face. Let's not prejudge the ability of
competing implementations to (a) speed up; (b) optimize namespace
search for common code. The first target has to be the programmer
using the language, not the implementor. This does not mean
implementor concerns do not matter, as I keep trying to reassure you
-- only that they come second.
In general, keeping the language simpler is good for performance.
Yet focusing on performance can complicate the language for
programmers. It certainly has for other languages.
Other things being equal, simpler implementations are easier to
change, and have more room to add complexity for optimization
without becoming too complex for human understanding.I will agree that some added language features are essential but I
think minor improvements in expressiveness that have large
complexity cost are a poor tradeoff.
Hard to disagree without more details. This is motherhood and apple
pie stuff.
This is a good trade-off if it can be done in reasonable
footprint, since there is a huge installed base, and a pretty-big
knowledge base. We're not, for example, going to remove the
ability to replace String.prototype.charAt, in any compatible ESn
version.Preserving compatibility with existing performance-harming features
is not the same thing as introducing new ones.
Since I did not say it was, I'm not sure why you are writing this.
Obviously the bone of contention is benefit to programmers vs. cost
to implementors. You allow as how the language must grow, which is a
challenge to implementors, if not to programmers (who should see
reduced need for boilerplate and library solutions). So we should get
back to details.
Programmers have found ways to live with today's performance, and
it is true that for some applications core language performance is
not the bottleneck. But that doesn't mean we can feel free to
ignore performance considerations in the design of new language
features.
Yeah, yeah.
I do not mean to blow off this point. We've discussed performance and
footprint throughout the last two+ years. No one feels free to ignore
performance considerations, and what I wrote did not ignore those
considerations.
I suspect the answer to this in AS3 is that if you want
performance, you have to use type declarations.That may be the case for AS3 code using Flex, but even such a
result would be informative -- don't open multiple namespaces if
you're using untyped objects and targeting an unoptimized
implementation.But really, why is any of the several feature combinations that
could hurt performance (with, eval, deep scope chains and
prototype chains in most implementations) a reason to cripple the
language? Performance is not king, and JS ain't C++.Is removing unqualified import of namespaces at non-global scope
(the only aspect of namespaces that seems prima facie harmful to
performance) really "crippling the language"?
Depends on how much you value 'use namespace intrinsic' in
particular, and the ability open "expert" or "version2" namespaces
that cut across programs, classes, and objects in ES4 applied to
large-scale programming in general.
I want to say thanks for making this proposal (open namespace search
only for lexical references). It leaves most of the use-cases I cited
intact. Well done, good compromise (not complete evisceration of
property qualifiers, or dismissal of unqualified import).
The helper/informative usage in the RI does open those namespaces,
and intrinsic works only as a cross-cutting namespace that can be
opened via pragma. So we should focus on these, if only to agree to
disagree on the importance of the former, argue for hardcoding the
latter via a separate early-binding pragma, and so forth.
Brendan Eich wrote:
I want to say thanks for making this proposal (open namespace search
only for lexical references). It leaves most of the use-cases I cited
intact. Well done, good compromise (not complete evisceration of
property qualifiers, or dismissal of unqualified import).
Likewise. It's an important distinction to have made and I'm glad you made it. Gives the discussion clearer texture. I'm mostly sitting out the argument here, but there are good points being raised and it's good to explore around them.
The helper/informative usage in the RI does open those namespaces,
and intrinsic works only as a cross-cutting namespace that can be
opened via pragma. So we should focus on these, if only to agree to
disagree on the importance of the former, argue for hardcoding the
latter via a separate early-binding pragma, and so forth.
Deploying a 'use namespace intrinsic' pragma does more than give early-binding opportunity to ES3 code (which, realistically, you'll need to do some extra type-level work to fully resolve). More importantly, it grants a one-switch migration point from mutable prototype slots (compatible) to fixed class slots (predictable). IOW it's a semantic, program-integrity feature.
This is IMO the more serious issue we're missing in the discussion. I want to elaborate on it here for the sake of clarity. What we have now is the ability to take ES3 code such as:
var x = "hello";
x.split("e");
and, by putting "use namespace intrinsic" at the front of it, make a rather drastic upgrade in its "integrity" (by at least some measure, see below). The call x.split() changes from a prototype-resolved lookup on a dynamic property (likely to resolve at String.prototype.public::split()) to a lookup that stops with the fixture intrinsic::split() defined on the class ES4::string, that x is an instance of. This fixture has the following "improved" nature:
-
It has fixed semantics! the user knows what they're getting and no 3rd party code twiddling String.prototype will change it.
-
It so happens that we "improved" the semantics by sticking dynamic typechecks on the boundaries of intrinsic::split(), so you'll get more type-error checking.
-
It can be cached and reused w/o worrying about cache invalidation due to mutation of String.prototype. The implementation can get adequate performance without having to play as-subtle tricks.
Moreover, a single "use namespace intrinsic" will upgrade an entire compilation unit at a time (or a limited scope within one) using this technique, without having to go through and modify every x.split() to x.improved_split().
I'd be curious to hear if there's another well-developed way to provide this sort of thing. I guess it could be done by some sort of pragma that is specific to the standard library, but the current technique will work for helping other library authors (dojo / yui / etc.) provide an integrity-upgrading facility for their users too. It'd be nice to make this technique usable to all.
(The same technique can be used to e.g. provide debugging-heavy variants of methods, or side-by-side usable "new" versions in the presence of "old" versions, that you toggle by opening namespaces. I have less experience with this, but IIRC it was part of Waldemar's the initial motivation.)
On May 27, 2008, at 12:18 PM, Mike Shaver wrote:
2008/5/27 Maciej Stachowiak <mjs at apple.com>:
It could save a lot of complexity, by not requiring any first-class
support for namespace lookup on arbitrary objects.Is the expectation then that having two lookup models, one for global objects and the other for non-global objects, going to provide less complexity?
My proposal is that there is one for lexical scope lookup along the
scope chain (which considers open namespaces when binding unqualified
names) and another for property lookup qualified to an object
reference (which does not). Yes, I believe this will provide less
complexity, because the scope chain and prototype chain algorithms are
quite complex in the current proposal and not the same as each other.
My rough proposal would greatly simplify the prototype chain algorithm
and not make the scope chain algorithm any more complex (it may become
simpler).
In a browser, "window" is the global object; would property lookup on "window" be namespaced when referenced as such? When you have a handle to another window? When you use |this.prop| in a global function?
My proposed answer to all of these would be no.
If we have namespace-aware lookup, it seems to me that it would be less complex for implementors and script authors alike for it to always apply, rather than just for one magical object.
I think it would be simpler to limit the effect of namespaces to
lexical bindings (where we know we can bind to the right name and
namespace statically in any case of interest) and not have them affect
object property lookup in general.
, Maciej
On May 27, 2008, at 1:07 PM, Brendan Eich wrote:
On May 27, 2008, at 11:42 AM, Maciej Stachowiak wrote:
On May 27, 2008, at 11:00 AM, Brendan Eich wrote:
What's at issue is whether and why unqualified import matters in
any object, even the global object only, since the NAS proposal
did not allow unqualified import even at global level, and the use- case for unqualified import was dismissed as not compelling.There's really 4 separable issues:
- Namespacing of names at global scope (via lexically scoped
reference).- Unqualified import of names into global scope.
- Namespacing of arbitrary object properties.
- Unqualified import of namespaces for arbitrary object properties.
I would claim 1 and 2 are essential, 3 can be done by convention in
the absence of 4 (a la the NAS proposal) and 4 is unnecessary and
harmful to performance.Thanks, this is helpful, since the argument you joined was about (2)
and/or (4) -- there is no unqualified import in the NAS sketch.I forgot one of the main use-case for 4, one you've expressed
interest in already: 'use namespace intrinsic'. Without (4), this
does not allow early binding for s.charAt(i) given var s:string to
string.prototype.intrinsic::charAt.
Yeah, but you can't early bind this anyway if s lacks a type
annotation (or you otherwise have inferred that s is of string type).
In fact if you can't infer the type of s then you get worse
performance than if you hadn't opened any namespaces. Plus lookup of
any property names that couldn't have been early bound at all if the
exact type had been inferred is likely to suffer. So I'm not sure any
more it is good to encourage adding "use namespace intrinsic" to
otherwise unchanged ES3 programs.
But you do have my number - I like the potential for early binding
both for program understandability and performance. I would love to
see a way to make it possible without at the same time making property
lookup in the face of unknown types slower. I will think about it
myself but perhaps someone else will come up with something clever.
As for my motherhood & apple pie lecture, it is based on experience
with a working on a high-performance production-quality JavaScript
implementation. We managed to pretty much rewrite the core interpreter
for a significant performance boost in about two months, and that was
struggling against the existing complexity of de facto JavaScript (ES3
- some Mozilla extensions). Along the way we found some correctness
bugs that exist in pretty much all existing implementations
(sequencing considerations in the face of exceptions for instance). If
the language were much more complex, then it would be much harder to
make architectural changes of the implementation. I believe this is a
quality worth preserving. Well-engineered tight code can sometimes
beat the fanciest of rocket science optimizing implementations simply
because it is easier to understand and therefore measure and optimize.
(To some extent, this applies less to pure syntactic sugar that can be
represented in terms of core language constructs, which is why I worry
more about complex semantics.)
I want to say thanks for making this proposal (open namespace search
only for lexical references). It leaves most of the use-cases I
cited intact. Well done, good compromise (not complete evisceration
of property qualifiers, or dismissal of unqualified import).
Thank you for saying so. I wonder what Mark thinks? (For the record, I
think open namespaces as affecting lexical scope only would also
remove the need for first-class Name objects.)
The helper/informative usage in the RI does open those namespaces,
and intrinsic works only as a cross-cutting namespace that can be
opened via pragma. So we should focus on these, if only to agree to
disagree on the importance of the former, argue for hardcoding the
latter via a separate early-binding pragma, and so forth.
I'm not sure there is a good design for an early binding pragma is
that is immune to the performance costs. One possibility I can think
of is to it an error to access a property by an early-bound name on an
object that lacks the early-bound version when the pragma is in effect
(without explicitly qualifying it as not subject to early binding).
That seems potentially icky.
, Maciej
On Wed, May 28, 2008 at 2:46 AM, Maciej Stachowiak <mjs at apple.com> wrote:
I think it would be simpler to limit the effect of namespaces to lexical bindings (where we know we can bind to the right name and namespace statically in any case of interest) and not have them affect object property lookup in general.
OK, that would be simpler, though I do worry about breaking the "window.whatever is the global whatever" model a bit for web developers. Thanks for the explanation.
Given that namespaced lookup is used on the scope chain, |with (window)| would then do namespaced lookups, albeit perhaps more slowly? Does that also mean that |with (someobj)| will be a way to get namespaced lookup on non-global objects?
Mike
On Wed, May 28, 2008 at 12:48 AM, Maciej Stachowiak <mjs at apple.com> wrote:
I want to say thanks for making this proposal (open namespace search only for lexical references). It leaves most of the use-cases I cited intact. Well done, good compromise (not complete evisceration of property qualifiers, or dismissal of unqualified import).
Thank you for saying so. I wonder what Mark thinks?
Hi Maciej, I'm still absorbing, so I don't completely get it yet. But I do like the direction a lot. It seems to be a big improvement.
(For the record, I think open namespaces as affecting lexical scope only would also remove the need for first-class Name objects.)
Yes, this is the clearest sign of how big an improvement. Variable lookup would once again be looking up a programmer-written identifier in a lexical environment to get a location, as opposed to the draft ES4 spec's double lookup (looking up an identifier to get a Name, and then looking up a Name to get a location). IIUC, it moves the complexity into the nature of the lexical environment handling the lookup, but that's it. Do I have this right?
Frankly, I won't have time to look at it more today. Perhaps you could do an informal presentation on it at the Thurs/Fri meetings coming up in SF?
On Wed, May 28, 2008 at 12:48 AM, Maciej Stachowiak <mjs at apple.com> wrote:
I want to say thanks for making this proposal (open namespace search only for lexical references). It leaves most of the use-cases I cited intact. Well done, good compromise (not complete evisceration of property qualifiers, or dismissal of unqualified import).
While I like the idea, it doesn't address at least two of the use cases for namespaced properties:
- Having both a fully typed and an untyped version of the same method on the object, allowing code to switch through just opening a namespace if the programmer knows their code is type consistent.
- Allowing user classes or objects to present interfaces overriding behaviour inherited from Object which were internal and unexposeed in ES3.
The first point is mainly a convenience feature.
The second point can be addressed using new syntactic forms for each such case. (If using the form "operator [no newlines here] ident", that would be a safe way to do it since all code looking like that cause a syntax error in ES3.) I don't know if that's a good or bad idea though.
On May 28, 2008, at 12:48 AM, Maciej Stachowiak wrote:
On May 27, 2008, at 1:07 PM, Brendan Eich wrote:
I forgot one of the main use-case for 4, one you've expressed
interest in already: 'use namespace intrinsic'. Without (4), this
does not allow early binding for s.charAt(i) given var s:string to
string.prototype.intrinsic::charAt.Yeah, but you can't early bind this anyway if s lacks a type
annotation (or you otherwise have inferred that s is of string
type). In fact if you can't infer the type of s then you get worse
performance than if you hadn't opened any namespaces.
That depends on the implementation, but let's say it's true. You
still get the better-typed fixtures (the string class's
intrinsic::charAt method) instead of possibly overridden prototype
properties.
The 'use namespace intrinsic' design for early binding grew out of
the "compact profile" of ES3, which is a dead letter on the web
because it's overtly incompatible (the spec is short enough to read
in a few minutes: www.ecma-international.org/publications
standards/Ecma-327.htm). A pragma for prioritizing fixed methods with
stricter type signatures was prototyped by the strict mode in AS3.
During collaborative ES4 development in TC39 TG1, we synthesized
aspects of these precursors into 'use namespace intrinsic'.
This design is implemented in the ES4 RI, and it will probably be in
a couple of practical open source implementations this year. We want
to get user as well as implementor feedback.
But you do have my number - I like the potential for early binding
both for program understandability and performance. I would love to
see a way to make it possible without at the same time making
property lookup in the face of unknown types slower. I will think
about it myself but perhaps someone else will come up with
something clever.
Great. In the mean time, we'll be working on clever solutions to
speed up all property lookups, even with open namespaces. Maybe we'll
convince you that cleverness is better applied by implementors to
enable programmers who benefit from new things like cross-cutting
intrinsic, debugging, version2, etc. namespaces.
As for my motherhood & apple pie lecture, it is based on experience
with a working on a high-performance production-quality JavaScript
implementation. We managed to pretty much rewrite the core
interpreter for a significant performance boost in about two
months, and that was struggling against the existing complexity of
de facto JavaScript (ES3 + some Mozilla extensions). Along the way
we found some correctness bugs that exist in pretty much all
existing implementations (sequencing considerations in the face of
exceptions for instance). If the language were much more complex,
then it would be much harder to make architectural changes of the
implementation.
Two months. Sorry, but if it took you three or four months to do that
and also include namespace optimizations, but the benefit to the
great many JS or would-be ES4 programmers were enough, then why
wouldn't you take the extra month or three?
Given the needs of the many and the scale of the web, I continue to
believe that the main argument should be about maximizing usable
utility for programmers writing in the new version of the language --
only secondarily about hardships for implementors who make the big
bucks making JS go fast :-/.
On 5/27/08 8:45 AM, Maciej Stachowiak wrote:
Is the cost too high? I think that depends on how the name lookup algorithm works on real-world code. AS3 developers have data to share. Let's get into that.
You looking at me? ;-) I don't have that data, but I'll gladly see if I can find some.
I'd love to hear the data. AS3 developers, can unqualified lookup of object properties on untyped references in the presence of property namespaces be as fast as when there aren't namespaces at all?
Seems unlikely since more work is being done.
If so, how? The most obvious way to do property lookup when there is no static type info is a hashtable lookup on each prototype chain entry, but I do not see an obvious way that a single hashtable lookup can look in multiple namespaces. I suspect the answer to this in AS3 is that if you want performance, you have to use type declarations.
Some of the complexity in the name resolution algorithms is to ensure that references to fixed properties cannot be shadowed. This means, with or without static type information, references to fixtures need only be resolved once. So the incremental cost that is incurred during unqualified name lookup is amortized across multiple evaluations of the reference in which it occurs.
Other bits of complexity in those algorithms is there to disambiguate names in the case of conflicts. It would be interesting to study how often this code gets invoked in practice. It might not come into play all that often.
On May 28, 2008, at 8:25 AM, Mark S. Miller wrote:
(For the record, I think open namespaces as affecting lexical scope only would also remove
the need for first-class Name objects.)Yes, this is the clearest sign of how big an improvement. Variable lookup would once again be looking up a programmer-written identifier in a lexical environment to get a location, as opposed to the draft ES4 spec's double lookup (looking up an identifier to get a Name, and then looking up a Name to get a location).
Just for the record, Name objects arise in the reflection API in ES4,
and they came up originally via the combination of for-in loop
enumeration and namespaced property identifiers. So:
for (let name in obj) print(obj[name]);
should work given:
let obj = {ns::prop: 42};
and name will be bound to a Name instance with qualifier ns and
identifier "prop". The disclosure of Name instances via for-in
implies the ability to compute a property name by indexing an object
with a Name instance (the disclosed instance).
We've since decided not to return Name instances from for-in's
underlying iterator -- that is, non-public-qualified property
identifiers are not enumerated. The motivation for obj[name] and the
reflection APIs remains strong in ES4.
-----Original Message----- From: es4-discuss-bounces at mozilla.org [mailto:es4-discuss-bounces at mozilla.org] On Behalf Of Brendan Eich Sent: 29. mai 2008 13:49 To: Mark S. Miller; Maciej Stachowiak Cc: es4-discuss at mozilla.org es4-discuss; Mark Miller; Douglas Crockford Subject: Re: Namespaces as Sugar (was: complexity tax) ... We've since decided not to return Name instances from for-in's underlying iterator -- that is, non-public-qualified property identifiers are not enumerated. The motivation for obj[name] and the reflection APIs remains strong in ES4.
It's a little more subtle than that, as the underlying iterator returns only public names (as strings) by default, but it is possible to feed the iterator constructor a set of namespaces, and if that is done then it will return Name objects for all the enumerable properties whose namespace is among the ones fed to the iterator constructor.
The reflection interface will have something similar but that design is far from finished.
On Sun, May 25, 2008 at 1:16 PM, Mark S. Miller <erights at google.com> wrote:
JavaScript already allows non-identifier strings to be used as property names. However, such non-identifiers cannot be used with the '.' syntax, and must be quoted in the object literal syntax, so they are generally avoided.
ES4 grammar contains the productions
NameExpression ::= Identifier | NamespaceExpression "::" PropertyIdentifier
NamespaceExpression ::= NameExpression | StringLiteral
// Used in object literals FieldName ::= NameExpression | ...
// Used to access a property PropertyOperator ::= "." NameExpression | ...
Good enough. Rather than invent new semantic concepts of Name and Namespace objects, we could just have these expand into non-identifier strings consisting of components (typically identifiers) separated by some kind of path separator string. The most logical choices for path separator would probably be either "::" or ".". For clarity in this note, in order to keep the levels distinct, I will use the path separator "/". Note that my actual preference would be "::".
So, for example, the program
is syntactic sugar for
This use of NamespaceExpressions will be familiar from XML. The value of the NamespaceExpression can be a longer string, allowing us to refer to long fully qualified names using short locally defined names.
As with XML namespaces, this proposal does not allow namespaces to be what ES4 calls "open". In other words, namespace-qualified names would always be explicitly qualified.
The proposal above is only for a syntactic convenience. It would not expand the semantics of the language at all.