<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><div>On May 27, 2008, at 8:45 AM, Maciej Stachowiak wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div><div>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.</div></div></blockquote><div><br></div>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).</div><div><br></div><div><br><blockquote type="cite"><div><blockquote type="cite"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><blockquote type="cite"><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><span class="Apple-style-span" style="-webkit-text-stroke-width: -1; ">One can certainly question the need for any namespacing of object  </span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">properties, let alone unqualified import of namespaces for such <span class="Apple-converted-space"> </span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">purposes.</div></blockquote><div><br></div><div>I hope so. I'd rather have someone question unqualified import than implicitly dismiss it, which is what seems to be happening.</div></div></div></blockquote><div><br></div><div>I don't see how your statement is responsive.</div></div></blockquote><div><br></div>Hey, I was agreeing with you (Mr. Assistant District Attorney Sir :-P). Questioning is fine.</div><div><br></div><div>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.</div><div><br></div><div>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.</div><div><br></div><div><br></div><div><blockquote type="cite"><div><div> 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.</div></div></blockquote><div><br></div>Sure you do, below where I gave particulars that led to the generalized namespace scheme in ES4.</div><div><br></div><div><br><blockquote type="cite"><div><blockquote type="cite"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><blockquote type="cite"><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">but does not mean namespaces need to generalize beyond the global <span class="Apple-converted-space"> </span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">scope. For example, global unqualified namespace import could desugar <span class="Apple-converted-space"> </span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">(logically) into the injection of scope chain items instead of into a <span class="Apple-converted-space"> </span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">general property lookup mechanism.</div></blockquote><br></div><div>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.</div></div></blockquote><div><br></div><div>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.</div></div></blockquote><div><br></div><div>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.</div></div><div><br></div><div><br><blockquote type="cite"><div><div> 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,</div></div></blockquote><div><br></div>Lexical context, no dynamic open-namespaces scope.</div><div><br></div><div><br><blockquote type="cite"><div><div> and it seems likely it will slow down property lookup when multiple namespaces are open but static type info is missing.</div></div></blockquote><div><br></div>It certainly could, although we think not in implementations under way. Opening multiple namespaces without is not free in a dynamic language.</div><div><br></div><div>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.</div><div><br></div><div><br><blockquote type="cite"><div><div> If the only real justification is that it's a nice generalization, then I do not think it is worth the performance hit.</div></div></blockquote><div><br></div>The nice generalization followed from particular use-cases, it did not precede them. I cited those cases (briefly). How about being responsive to them?</div><div><br></div><div><br><blockquote type="cite"><div><blockquote type="cite"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><span class="Apple-style-span" style="-webkit-text-stroke-width: -1; ">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.</span></div></div></blockquote><div><br></div><div>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.</div></div></blockquote><div><br></div>C++ and Java are not the right paradigms for JS/ES. Python is better, but Python *does* allow import in local scope.</div><div><br></div><div><br><blockquote type="cite"><div><div><span class="Apple-style-span" style="-webkit-text-stroke-width: -1; ">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.</span></div></div></blockquote><div><br></div>See Mark's big <a href="http://www.nabble.com/Classes-as-Sugar-(was%253A-Renaming-ECMAScript-4-for-the-final-standard-)-td16266635i20.html%23a17461937">post</a>, which discusses (in item (b)) extending objects, including standard ones.</div><div><br></div><div>Saying the global object is a shared resource that must be partitioned, etc., but <i>no</i> 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 <i>necessarily</i> shared object does not reduce the benefit, or make the cost prohibitive, of sharing other objects reachable from it.</div><div><br></div><div>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.</div><div><br></div><div>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.</div><div><br></div><div><br><blockquote type="cite"><div><blockquote type="cite"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><span class="Apple-style-span" style="-webkit-text-stroke-width: -1; ">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).</span></div></div></blockquote><div><br></div><div>Nontheless, the global namespace is unique. There's no way to replace the global object.</div></div></blockquote><div><br></div>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.</div><div><br></div><div>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.</div><div><br></div><div>The arguments so far are not going to make or break namespaces as proposed, by themselves. Moving along:</div><div><br></div><div><br><blockquote type="cite"><div><blockquote type="cite"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><span class="Apple-style-span" style="-webkit-text-stroke-width: -1; ">Also, JS hackers often prototype in global code and then push things down into closures or sub-objects.</span></div><div><br></div><div>Then there is the namespaces-for-versioning idea, which wants to cut across classes as well as global objects.</div><div><br></div><div>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 <i>is</i> 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.</div></div></blockquote><div><br></div><div>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.</div></div></blockquote><div><br></div><div>First, performance is not king or JS would not have prototypes and dynamic typing. It's not a trump card.</div><div><br></div>Second (after all the warm-up sparring), you didn't respond to the particulars that led to the generalization:</div><div><br></div><div>* internal namespace per compilation unit for information hiding -- hardcode as a special case?</div><div>* iterator and meta hooks in objects. Ugly __get__, etc., names instead?</div><div>* helper_foo() and informative_bar() in the RI?</div><div><br></div><div>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.</div><div><br></div><div><br><blockquote type="cite"><div><blockquote type="cite"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><span class="Apple-style-span" style="-webkit-text-stroke-width: -1; ">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.</span></div></div></blockquote><br></div><div>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.</div></blockquote><div><br></div>Competitively optimizing JS, excluding namespaces, increasingly requires non-obvious implementation techniques.</div><div><br></div><div>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.</div><div><br></div><div>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.</div><div><br></div><div>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.</div><div><br></div><div><br><blockquote type="cite"><div> I suspect the answer to this in AS3 is that if you want performance, you have to use type declarations.</div><div></div></blockquote></div><br><div>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.</div><div><br></div><div>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++.</div><div><br></div><div>/be</div></body></html>