Hi Mark, After looking at your posts, I do have a feeling that what you actually trying to solve is not a namespacing but modules scope encapsulation. Besides they way you're proposing to solve this is not really suits well for the interpreted language. I would recommend you to look into commonjs, ( http://commonjs.org/, http://wiki.commonjs.org/wiki/Modules/) I think it solves the problem nicely without extending language itself. One more interesting to look at http://www.cmlenz.net/archives/2009/12/namespaces
-- Irakli Gozalishvili Web: http://rfobic.wordpress.com/ Phone: +31 614 205275 Address: Taksteeg 3 - 4, 1012PB Amsterdam, Netherlands On Fri, Dec 4, 2009 at 03:59, Mike Samuel <[email protected]> wrote: > 2009/12/3 Mark A. Ziesemer <[email protected]>: > > On Thu, Dec 3, 2009 at 12:37 PM, Mike Samuel <[email protected]> > wrote: > > > >> Thanks for responding in such detail. > >> I have responded inline, but to summarize what I think I've understood > so far: > >> (1) This is a proposal for an added function, without any proposed > >> syntactic sugar > > > > Agreed, it is a proposal for an added function. Not sure about the > > proposed syntactic sugar. > > > >> (2) The function can be implemented as a library function as in your > blog post > > > > Agreed, though this would only be for compatibility until implemented > > natively. A similar example of this is > > > https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/forEach#Compatibility > > . > > > >> (3) The goal is to reduce the chance of unintentional namespace > >> collisions by code that is aware of the namespace function. > > > > Agreed, though not only between code that is aware of the namespace > > function, but also allowing code that is aware of the namespace > > function to better package itself (use no more than 1 global > > variable), to reduce the chance of collisions with code that is not > > aware of the namespace function. > > Quite. But the collisions are reduced only one way with legacy code. > If code is not aware of the namespace function, then it can still > clobber code that is. > > > >> (4) It is not a goal to prevent namespace collisions between code > >> written before the namespace function and code written after. > >> Specifically, if legacy code did "com = 'foo'" then namespacing would > >> be broken for all subsequent code. > > > > Somewhat. Any children of "com" would no longer be accessible by > > "com". However, any code within the closure(s) that was a child of > > com could possibly continue working properly, but just not able to be > > externally referenced. Furthermore, if something did run that > > reassigned "com", as long as that other code was just using it > > temporarily, the reference could be "backed up and restored". For > > example: > > Ok, so code that is aware of legacy code that clobbers a namespace can > workaround the fact as long as both don't depend on the namespace > surviving after they've run. > > > > > namespace("com.example.something"); > > // com.example.something is further populated. > > > > // Legacy JS now needs to be included, which uses "com" as a temporary > > String variable. > > // We are aware of this, and will handle accordingly. > > > > // Backup: > > var comBackup = com; > > > > // Allow legacy code to run: > > legacyCode(); > > // com now is "1234", but will actually never be referenced by the > > legacy code again. Restore: > > com = comBackup; > > delete comBackup; > > > > // com.example.* can now be referenced as intended. > > > > This is already an issue and a practice with namespace variables, such > > as "$" used in jQuery. See > > http://docs.jquery.com/Using_jQuery_with_Other_Libraries . > > An issue that namespace() does not address. > > >> So is it your argument that both (prefixing and dotted path > >> namespacing) are conventions that address the same problem, but that > >> the java-esque package name convention is a better convention? > > > > Somewhat. Both conventions help to eliminate naming collisions. > > eliminate -> mitigate? > > > However, the "dotted path" namespacing respects the global namespace, > > where as every namespace created using prefixing is another entry in > > the global namespace. > > Now you get at most one global entry per TLD. > > > > There have been some concerns that using the nested objects may affect > > performance, due to having to resolve multiple entities. However, > > I've not seen any results of any tests that show this to be true, or > > at least not with any significant additional expense. This is further > > Here is a console session from the squarefree shell on FF3.5 > > (function () { var abs = Math.abs; var t0 = Date.now(); for (var i = > 100000; --i >= 0;) { abs(-1); } var t1 = Date.now(); return t1 - t0; > })() > 9 > var js = {}; js.lang = {}, js.lang.Math = { abs: Math.abs } > [object Object] > (function () { var t0 = Date.now(); for (var i = 100000; --i >= 0;) { > js.lang.Math.abs(-1); } var t1 = Date.now(); return t1 - t0; })() > 65 > > Using a 4 deep path vs a local variable results in about a 7x slowdown. > > > > mitigated through "aliasing" as previously demonstrated. I think the > > True. This aliasing will of course defeat a lot of the dynamism, such > as using getters to do lazy loading. > I suppose minifiers and optimizers could introduce aliases at the top > of a closure to do some optimization, but only if the namespace name > is statically determinable. Essentially what is described at > > http://www.daveoncode.com/2009/12/01/custom-javascript-classes-packages-using-goog-provide-and-goog-require/ > > > same performance concerns could be valid with prefixing, as the large > > number of objects created at the global level can also hinder > > performance, as hash functions used in the implementation for the > > lookups may become less-than-optimal for a large number of items. > > Even if it doesn't hinder the performance of the runtime, consider > > tools such as the DOM inspector in Firebug. The window works much > > better with 10,000 objects stored in a tree structure with only 20 or > > so objects at the top level, rather than having all 10,000 objects > > displayed at once. > > > >> Have you quantified the cost of each module carrying their own > >> namespace creating code? > >> The bit in your blog about the minified form of the namespace function > >> suggest that it is low. > > > > The issue isn't so much about the amount of code. One issue is that > > Code size is an issue for many people. > > > each module that uses a namespace function also needs to make sure > > that such a function is properly named or namespaced as to not > > conflict with a similar namespace function in other modules. It is > > also difficult to encourage the use of namespacing when a proper > > method to utilize namespacing is not readily available. I don't agree > > that each module should have to include this additional boilerplate > > code. > > They will until/if 90+% of browsers support your namespace function. > > >> And if the function is in the minimized code, then can't minifiers do > >> a better job since they can do whole program analysis to use an > >> identifier smaller than the 9 character namespace, whereas if > >> "namespace" where externally defined, the 9 character name could not > >> be shortened. > > > > I'm somewhat confused. While the implementation of "namespace" may be > > minified, the reference to the "namespace" function itself should > > never be minified. This is part of my proposal - it should be made > > globally available. Also, if/once made part of the language standard, > > the will be no need to include the implementation of the "namespace" > > function, other than for backwards-compatibility, as mentioned above. > > Yes, but if they carry the code themselves then a code optimizer can > convert > function namespace(qname) { ... } > namespace('foo.bar') = ... > // many more > to > function a(qname) { ... } > a('foo.bar') = ... > // many more > saving space when 7 * nCalls > namespace.toString().length > > I suppose if the namespace function is a const, they could provide a > local short name by aliasing, so please ignore. > > > >> Since we are talking about language extensions, we need not be limited > >> by the approaches that are easy in ES3. > >> We can consider approaches that use other language primitives (like > >> lexical scopes in Ihab's module proposal) to address the same goals as > >> namespace. > > > > Does this even need to be considered a language extension? Nothing > > ES-harmony is talking about language extension. > > > I'm proposing is changing the language specification - just making an > > additional function available globally and by default. This will also > > allow it to be easily "back-ported" (as with the Array extras, etc.), > > allowing the function to be used to aid against an immediate and > > growing issue (naming collisions, etc.) > > > > >> Let me make sure I understand. > >> Let's say you have a file foo.js that inroduces one API element > >> com.ziesemer.foo. There are two namespaces: > >> com > >> com.ziesemer > >> as a result of > >> namespace('com.ziesemer').foo = ...; > >> > >> com.ziesemer.foo is not a namespace, since it is not created as a > >> result of the namespace function, right? > > > > I'm not necessarily encouraging this, but "foo" could be a function, > > but could also act as another namespace level. For example, all of > > the following could be valid: > > > > com.ziesemer.foo("bar!"); > > com.ziesemer.foo.child(); > > com.ziesemer.foo.a.b(); > > > >> So for namespaces to be dynamic, means it would be OK for com.ziesemer > >> to be implemented in terms of a getter -- e.g. to allow lazy loading? > > > > I have to think more on this. Need to review the concept of "getters" > > in the language. > > Section 8.12 of the spec defines the semantics. A good starting point > might be 15.2.3.6 Object.defineProperty. > > >> > any reason to introduce artificial limitations to prevent doing so. > >> > >> There are more clients for javascript programmers than just > >> programmers and interpreters. There are debugging tools, minifiers, > >> IDE auto-completers, documentation generators, etc. > > > > I don't see anything that conflicts with this. This practice is > > already being used increasingly, and I've not seen any related issues > > - including with debugging tools e.g. Firebug, or minifiers such as > > the YUI Compressor. > > >> >> Why is namespace not in a namespace? > > > >> Lots of systems require bootstrapping. In java, there is no paradox > >> when it comes to which ClassLoader loaded the Class or ClassLoader > >> classes? > > > > True. The same could be done as: > > > > var com = {}; > > com.example = {}; > > com.example.namespace = function(){ /* ... */ }; > > > > com.example.namespace("com.example.test"); > > > > The better argument against this is probably that then every library, > > etc., that wants to namespace will have to call > > "com.example.namespace(...)" instead of just "namespace(...)". While > > not impossible, it seems silly to bury what should be such a > > fundamental function. > > Perhaps I just don't understand why it is so fundamental. > It seems that if OO namespacing becomes the norm, most code modules > will look like > (function () { > // aliases to externs > var foo = namespace('com.foo'); // or an imports object composed > from import...as decls > > // core code > > // export definitions -- 1 use of namespace > mixin(namespace('com.bar'), { export1: ..., export2: ... }) > })() > So it seems that it wouldn't really be fundamental in core code -- > just idiomatic for import and export. > > > >> I appreciate that you're trying to codify existing practice. I'm > >> trying to help clarify the proposal by asking these questions. Lot's > >> of existing practices (JSON handling and getElementsByClassName come > >> to mind) have many subtle variants, so codifying is not a simple > >> matter of stamping approval on a concensus -- you still have to tease > >> out goals, enumerate candidates, discuss tradeoffs, understand legacy > >> code, etc. > > > > Perfectly agreed and appreciated. > > > >> This seems like a non-sequitur. > >> > >> If two pieces of code do > >> namespace('com.ziesemer') = ... > >> > >> namespace('com.jquery') = ... > >> isn't the com object a shared concern? Why is it "just an object"? > > > > I guess I don't see the issue. Following the namespacing practice, > > one shouldn't define anything that they don't "own". I could take > > ownership of "com.ziesemer" and assign things to it, or re-assign it. > > However, I don't own "com", so I shouldn't touch it. It is still just > > an object, just not one that anyone should pretend to own. > > But you do touch it. You add a 'ziesemer' property. > And if "ownership" is the right concept, on Rhino, it is owned by the > local environment. > > >> Wouldn't it be problematic for code to do something like (using the > .info TLD): > >> var info = loadUserInfo(); > >> > >> namespace('info.ziesemer').foo = ...; > > > > Probably. However, using "info" as a top level variable was the first > issue. > > Yep, just an example of another way for this to interact badly with legacy > code. > There are many other TLDs that might be names in the top level or IDs > exported since window includes document.all on IE -- travel, museum, > biz, int, us, etc. > > > Additionally, the goal for this proposal isn't necessarily to define > > the namespacing standard - just the function that can be used to > > create namespaces. Another standard - either along with or after this > > one - may clarify this. Also, if everyone just standardized on this, > > there would be no further work to do. (High hopes, I realize, but not > > impossible, or anything that I think should delay this proposal.) > > I don't know quite what a "namespacing" standard would look like, but > if your goal is to get large numbers of developers to do things "the > right way", a standard is not the right way to go. Standards can only > help a small group of developers coordinate, e.g. browser > implementors. > > I'm not yet convinced that namespacing is the problem to solve -- it > sounds like solving the module problem would moot namespacing. > > > >> If the first module creates an object, then the second will not modify > >> it. But the second is problematic in this case precisely because it > >> assumes things about info that are not true. If it is just an object, > >> instead of "an object that other packages can safely add properties to > >> without changing the meaning of namespace respecting programs" then > >> namespacing is broken. > > > > See above. I don't see any issues with both working together. > > > >> (I think in Rhino it's not just an object. If there's any com package > >> on the classpath, it's actually an immutable java package item that > >> allows Rhino to get at java classes.) > > > > Very true. However, again, this isn't an issue with the proposed > > namespace function itself, but the standard for how namespaces are > > created. > > True. It's hard to reason about how the namespace function should > behave without considering one or more naming schemes. > > > > IMO, the JavaPackage's of "com", etc., should be eliminated and > > instead referenced through the existing "Packages" JavaPackage. I.E.: > > "Packages.com.sun" instead of "com.sun". > > I don't understand Rhino internals well, but I think the two have > subtly different meanings. > I agree though. But Rhino and liveconnect do raise legacy concerns > for java-esque naming schemes. > > >> > I would say that namespaces should definitely not be marked > >> > "unconfigurable". A good JavaScript library, if it has nothing else > >> > to do and no more purpose, should actually remove itself from memory, > >> > and allow itself to be garbage collected. I don't see any reason to > >> > introduce any barriers to allowing this. > >> > >> How would this be done in practice? > >> How would a library know when to unload itself? > > > > I'd consider this to be out-of-scope of this discussion. However, > > it's probably more of an issue of not "how this would be done", but > > "it's probably the wrong approach, anyway". > > Ok, so supporting unloading of code modules is definitely not a goal > of the namespace function. > > > Such code should just be handled in a closure, so the entire thing can > > go out-of-scope and be GC'd when complete: > > > > (function(){ > > // Stuff... > > })(); > > But dependencies it loads and accesses via namespace(...) could not do > that. > Code that does not use namespace(...) to export don't require manual > deallocation, but their dependencies do. > > > However, for the point of this discussion: > > > > namespace("com.example.myApp"); > > namespace("com.example.helperA"); > > namespace("com.example.helperB"); > > > > "myApp" needs to utilize "helperA" and "helperB", but only > > temporarily. Additionally, during this time, "helperA" and "helperB" > > may call each other, which is why they need to have a namespaced > > reference defined outside of a closure. After this, "myApp" could > > remain, with the "helpers" removed: > > Only if myApp knows it "owns" helperA and helperB in the sense you used > above. > > > com.example.myApp.cleanupHelpers(); > > > > Where cleanupHelpers was previously defined as: > > > > com.example.myApp.cleanupHelpers = function{ > > delete com.example.helperA; > > delete com.example.helperB; > > }; > > > > More appropriately, both helpers could define their own cleanup() > > functions, that could delete themselves in the same way. > > Personally, I dislike imposing manual memory management on languages > that have a garbage collector. > But you're right that this is not a problem with the namespace > function, just with code loading schemes that depend on the global > scope. > > > >> If another approach to managing namespace collisions were to do this > >> better, would it be an argument against the OO namespacing approach? > > > > I wouldn't want to do anything to hinder further progress or > > enhancements around this. However, I don't think anything new would > > be an argument against what is being proposed. As mentioned > > previously, many libraries (especially the better ones) are already > > utilizing the OO namespacing approach. Right now, each library is > > creating and using their own "namespace" function. Scripting uses > > that currently aren't using a library must either consider using a > > library to obtain a namespace function, or define one themselves - at > > the risk of a naming collision for the namespace function itself, etc. > > Ok, but hermetic eval based loaders would allow those libraries to > work and take advantage of any namespace function without losing the > ability to choose your own name, and without adding anything to the > global scope which makes collection difficult. > > > I'm hoping that a provided namespace function can become standardized > > into the language, and made available at runtime to previous versions > > as demonstrated above. > > >> Do we agree that the ability to use `with` with OO namespaces is not a > >> feature of the proposal. > > > > Agreed, not a highlighted feature. It is something that probably > > should still be listed on a FAQ page, etc., that helps explain the > > usage and design, but also the previously mentioned links that show > > why it is not the best idea and why the other methods of aliasing > > should be used instead. > > > >> Java packages provide for many things. I am trying to understand via > >> your analogy which you see this as providing. As far as I can tell, > >> java packages provide: > >> (1) access control via package private and JAR sealing > >> (2) hierarchical addressing of classes > >> (3) some degree of namespace separation, though separation can also > >> be achieved by using multiple classloaders > > > > Even JAR sealing doesn't provide access control. Classes and methods > > within a sealed package can still be called. Sealing just means that > > additional classes in a sealed package can't be defined outside of the > > same JAR. > > > I don't think this is really applicable to this proposal, though. > > Agreed. Not applicable. > > >> > I guess I would consider the "private" and "protected" keywords more > >> > suited to "hiding" things than packages. Even then, these keywords > >> > are seldom misunderstood, and should never be used for "security". A > >> > little reflection can go a long way! > >> > >> I disagree with this. Reflection does not work around the access > >> control rules unless the VM invoker explicitly opts out. See Joe-E as > >> an example of security based on access running a subset of Java with > >> reflection enabled. http://code.google.com/p/joe-e/ > > > > True - as long as these details are understood. I was just saying > > that I see the "private" keyword being used way too often as a failed > > "security measure". > > > > > -- > > Mark A. Ziesemer > > www.ziesemer.com > > > _______________________________________________ > es-discuss mailing list > [email protected] > https://mail.mozilla.org/listinfo/es-discuss >
_______________________________________________ es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

