On Sep 7, 2004, at 6:26 AM, Dan Sugalski wrote:
*) Namespaces are hierarchical
So we can have ["foo"; "bar"; "baz"] for a namespace. Woo hoo and all that. It'd map to the equivalent perl namespace of foo::bar::baz.
How does this hierarchical nature manifest? I ask because I don't know of any languages which actually have nested namespaces, so I'm not sure what this is meant to imply. In particular, if this implies cascading lookup (meaning that a symbol looked up in ["foo"; "bar"; "baz"] would fall back to looking in ["foo"; "bar"] if it didn't find it), than that's not how Perl5 packages work.
If it doesn't mean that, then I can't come up with any non-contrived functionality that nested namespaces give us, over non-nested namespaces, other than slower symbol lookup.
*) Namespaces and sub-spaces can be overlaid or aliased
So code can, for example, throw a layer over the ['foo'; 'bar'; 'baz'] part of the namespace that gets looked at first when searching for something. These layers can be scoped and shifted in and out, which means its possible to have two or more ["IO"] namespaces that have completely (or partially) different contents depending on which space is in use.
I think I know what you are getting at, though it's a bit fuzzy still. But it may help to point out that Perl5 at least never "searches" multiple namespaces. If a variable is not found in any enclosing lexical scope, then it's looked up in the current package--no effort to determine which namespace to look in at all, actually. This loops back to my worry as to whether nesting implies fallback lookups.
It's also possible to hoist a sub-space up a few levels, so that the ["IO"] space and the ["__INTERNAL"; "Perl5", "IO"] namespace are the same thing
This seems like Tim's chroot-ing, I guess.
*) The top-level namespace ["__INTERNAL"] is taken. It's ours, don't touch in user code.
Alternate names are fine. I'm seriously tempted to make it ["\0\0"]
I don't see a need to name it. Since everything's relative to it, it should just be []. So the ["foo"] namespace is automatically relative to the root. No need to make up a reserved name (which is always dangerous).
*) Each language has its own private second-level namespace. Core library code goes in here.
So perl 5 builtins, for example, would hang off of ["__INTERNAL"; "perl5"] unless it wants something lower-down
*) Parrot's base library goes into ["_INTERNAL"; "Parrot"]
I'd say that the language-level namespaces should get nice reverse-DNS names, like ["com.perl.perl5"], or whatever's appropriate. This is sort of the modern, best way to avoid name clashes (because there's an authoritative definition of who "owns" a given name). This is especially important when people start implementing languages with multiple dialects, like Lisp.
Leopold Toetsch wrote:
...Dan Sugalski <[EMAIL PROTECTED]> wrote:
*) Namespaces are hierarchical
What do we do against collisions?
.namespace ["foo" ; "bar" ]
prohibits any "foo" global in the top-level namespace.
Not necessarily, but it does bring up a different problem. The "not necessarily" comes in because I think of "a" namespace as really being multiple lookup tables. That is, in Perl5 you can have a function "foo", a scalar "foo", an array "foo", and a hash "foo", all at the same time. So really, a lookup is typed--you have to have the equivalent of "look up the array named 'foo' in the 'blah' namespace" (or, "look up 'foo' in the array section of the 'blah' namespace"). In the above example, you'd be looking up "foo" in the namespace section of the root namespace, so you _could_ still have a variable or whatever in the top-level namespace.
But, this gets tricky right away: Perl5 has (arguably) a whole bunch of different "sections" in its namespace--function v. scalar v. array v. ...; Common Lisp has separate namespace for functions v. other symbols (you can have a function "foo" and a variable "foo"), but doesn't have segmented variable types; Scheme has a single namespace (so you only get one "foo").
So the problem here is that it would seem that Parrot should try to be agnostic about this sort of thing (and support different languages with different styles), but thing will get tricky when crossing between languages (eg, if Perl has $foo and @foo, which does "foo" resolve to from Scheme code; if Scheme code defines "bar", where does it end up from the perspective of Perl). And "agnostic" == "push the difference into the code gen done by the compilers" == "you can't optimize much", at least probably.
[[And you can't really side-step this in the Perl5 case by trying to treat the sigil as part of the variable name--for one because that's not really true, and for another because that would probably make Perl5-defined variable inaccessible from, say, Python code.]]
Tim Bunce said:
I think a filesystem analogy is a very helpful one. Many of the issues are similar and there's a lot of experience with how to address them in creative ways.
I'd suggest adding:
*) Each interpreter has a "current root namespace" from which namespace searches start. (Analogous to chroot() in unix.)
Apart from enabling functionality analogous to chroot() in unix, it also avoids having to prepend ["_INTERNAL"; "<language>"] to all namespace lookups and avoids the overhead of then traversing through those two levels.
There's a bit of a problem with that--in the previous thread you'd mentioned the "chroot" functionality as being part of the implementation of Perl's Safe module. That makes sense, but that would imply that you shouldn't be able to "climb back up", so that would conflict with using this as an optimization, it seems.
But I do think the multiple lookups is a problem (which is part of why I am looking for a tangible benefit that the nesting gives us). But I think an optimization can be had without any special support by Parrot--a compiler could emit code to, for example, lookup it's base namespace once, and stash that somewhere for later use, and have all of its namespace locating start from there. There seems to be a lot of "the current effective whatever" that languages will need (currently selected filehandle, etc.), so I hope there's a general way to optimize that.
*) Namespaces and sub-spaces can be overlaid or aliased
So code can, for example, throw a layer over the ['foo'; 'bar'; 'baz'] part of the namespace that gets looked at first when searching for something. These layers can be scoped and shifted in and out, which means its possible to have two or more ["IO"] namespaces that have completely (or partially) different contents depending on which space is in use.
I'd be interest to know your thoughts on how that that might be implemented. Seems like you'd need a 'sparse tree' of proxy namespace objects that you'd start searching first and that would fallback to the corresponding real namespace object at the point no match was found. But it doesn't seem worthwhile going into much detail till the "namespace traversal" bullet above is filled out.
(I'm reminded of the translucent filesystem (TFS), but it's effect is globally visible.)
(Or NFS unions mounts, and BSD whiteouts.)
This might help with my worry mentioned above, of how namespaces behave in light of code involving multiple languages, each with its own idea of how they are segmented with respect to different sorts of entities.
I think it's a bit of a language-specific question, as to how one could refer to something "above" ones usual language root. One solution is the back-linking you (Tim) mentioned previously, but I'm not sure if that's necessarily something that Parrot needs to supply--that is, I think this could be handled adequately at the language level. (For example, Perl5 currently has some special cases like CORE::GLOBAL; it could allow something like ABSOLUTE::Python::whatever, to specify a namespace via the analog of an absolute path.)
JEff