Addition of a global namespace function?

Irakli Gozalishvili rfobic at gmail.com
Fri Dec 4 05:20:47 PST 2009


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 <mikesamuel at gmail.com> wrote:

> 2009/12/3 Mark A. Ziesemer <online at mark.ziesemer.com>:
> > On Thu, Dec 3, 2009 at 12:37 PM, Mike Samuel <mikesamuel at gmail.com>
> 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
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20091204/08413189/attachment-0001.html>


More information about the es-discuss mailing list