We need namespaces. Duh. We talked about this in the past.
So, here's what I'm proposing. It'll be formalized into a PDD once we hash things out.
*) 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.
*) 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.
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
*) 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"]
*) 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"]
If this is fine, we can then go on to fight^Wdiscuss the standard aliases and such. I think it's time to start the parrot library project back up, which means we ought to deal with library versioning and such too. -- Dan
--------------------------------------it's like this------------------- Dan Sugalski even samurai d...@sidhe.org have teddy bears and even teddy bears get drunk -- Dan
--------------------------------------it's like this------------------- Dan Sugalski even samurai d...@sidhe.org have teddy bears and even teddy bears get drunk
> We need namespaces. Duh. We talked about this in the past.
> So, here's what I'm proposing. It'll be formalized into a PDD once we > hash things out.
> *) 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.
> *) Namespaces and sub-spaces can be overlaid or aliased
Can you say, in ["foo"; "bar"; "baz"], toss in a different namespace implementation for ["foo"; "bar"] and have that call some function with "baz"? Will this work if it's ["foo"; "bar"; "baz"; "quux"]?
>> We need namespaces. Duh. We talked about this in the past.
>> So, here's what I'm proposing. It'll be formalized into a PDD once we >> hash things out.
>> *) 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.
>> *) Namespaces and sub-spaces can be overlaid or aliased
>Can you say, in ["foo"; "bar"; "baz"], toss in a different namespace >implementation for ["foo"; "bar"] and have that call some function with >"baz"? Will this work if it's ["foo"; "bar"; "baz"; "quux"]?
Yes. Namespaces will work like any other aggregate accessed with a multi-level key -- they resolve as far as they can and pass on the remaining key to whatever things resolve to. Individual namespaces will likely be single-level affairs, so ['foo'; 'bar'; 'baz']] will have foo resolved by the top-level namespace, bar by whatever was in the foo slot, and baz by whatever was in the bar slot. (At which point you've got the final namespace and have to go look for whatever it was you were ultimately interested in) -- Dan
--------------------------------------it's like this------------------- Dan Sugalski even samurai d...@sidhe.org have teddy bears and even teddy bears get drunk
On Tue, Sep 07, 2004 at 09:26:14AM -0400, Dan Sugalski wrote: > Time to nail this.
> We need namespaces. Duh. We talked about this in the past.
I've reordered these to put the simple/fundamental things first:
> *) Namespaces are hierarchical > *) The top-level namespace ["__INTERNAL"] is taken. > *) Each language has its own private second-level namespace. > *) Parrot's base library goes into ["_INTERNAL"; "Parrot"]
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.
*) ...something here about namespace objects and how namespace traversal is performed (methods/vtable foo)...
> *) 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.)
> 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
Not actually "move", but "make visible at"? Like a symbolic or hardlink in a filesystem.
On Tue, 2004-09-07 at 09:26, 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.
[...] 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 sounds fine, except for the higher level question of who controls the root. That is, does a module Python decide to define its bits in the "Python" space AND export them to the root?
The other way to go is to say:
#!/usr/bin/perl6 use __Python::os;
Which has the interesting result that no one ever need touch the root. There's simply a search path that each language uses that would default to [] and its own ["__Internal";$language].
> Alternate names are fine. I'm seriously tempted to make it ["\0\0"]
Heehee. I don't think __INTERNAL is so bad.
> *) 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
Ok, so that's where "split" would go, right? Does that mean that if, in Python, I wanted to use Perl 5's split, I'd just have to:
import __INTERNAL.perl5 list = split '\\ba(?=b)', the_string, 5
> Dan Sugalski <d...@sidhe.org> wrote: > > *) Namespaces are hierarchical
> What do we do against collisions? During Pie-thon hacking I came along > this problem:
> class C(): > pass
> c = C()
> "C" ought to be now a "global" classname (that's what the bytecode > indicates) and it should be its own namespace for holding class methods.
> But the hash slot at "C" can only be used once.
> Or similiar:
> .namespace ["foo" ; "bar" ]
> prohibits any "foo" global in the top-level namespace.
> leo
While thinking about this very thing for a VM I was/am working on, a class isa namespace. And really, I'd probably start by implementing namespaces as a simple Hash. so, class isa namespace isa hash isa type. (type is my pmc like thing, I can't believe I thought about my "type" stuff before I started reading this list :o)
How well this will actually work for me or Parrot? I've no idea.
Thomas Fjellstrom wrote: > On September 7, 2004 09:15 am, Leopold Toetsch wrote: >>What do we do against collisions? During Pie-thon hacking I came along >>this problem: >>Or similiar:
>> .namespace ["foo" ; "bar" ]
>>prohibits any "foo" global in the top-level namespace.
>>leo
> While thinking about this very thing for a VM I was/am working on, a class isa > namespace. And really, I'd probably start by implementing namespaces as a > simple Hash. so, class isa namespace isa hash isa type. (type is my pmc like > thing, I can't believe I thought about my "type" stuff before I started > reading this list :o)
> How well this will actually work for me or Parrot? I've no idea.
I can think of two ways to go: 1) namespace name mangling. E.g each namespace name gets a '\x0' prepended. 2) a special kind of hash that allows one key holding a leaf name entry *and* a subnamespace hash.
> 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 <d...@sidhe.org> 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 Clites writes: > 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,
Other than, um, well, Perl.
> 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.
No, the lookup is not cascading downwards. It is cascading upwards, however, so that in:
[ "foo"; "bar"; "baz" ]
The [ "foo"; "bar" ] part can be implemented differently. This means that Python's namespaces and Perl's namespaces can have different semantics. Picture a PythonStash and PerlStash pmc.
> Jeff Clites writes: >> 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,
> Other than, um, well, Perl.
As an implementation detail yes, but I can't think of any Perl code (except for explicit introspection) which "reveals" this. That is, seemingly nothing about Foo::Bar comes out of Foo, nor is it necessarily related to Foo::Baz.
>> 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.
> No, the lookup is not cascading downwards. It is cascading upwards, > however, so that in:
> [ "foo"; "bar"; "baz" ]
> The [ "foo"; "bar" ] part can be implemented differently. This means > that Python's namespaces and Perl's namespaces can have different > semantics. Picture a PythonStash and PerlStash pmc.
Sure, if they're nested then the "baz" namespace is looked up inside of "bar" which is looked up inside of "foo"--I get that. But what I'm wondering is, let's say you have $Foo::Bar::someVariable (in Perl5 syntax). That means "look up $someVariable, inside of the Foo::Bar namespace". Now, let's contrast two ways this namespace name might compile down:
["Foo"; "Bar"]
v.
["Foo::Bar"]
Now, what would behave differently in those two cases, in terms of the behavior of $Foo::Bar::someVariable? I can't think of anything.
Now it's true that if you think it's really important to tie namespaces such that you can take over the name resolution for ["Foo"], then you'd want the former. But I don't see that as really terribly useful--in the examples I've heard of (e.g., turning the namespace lookup into an Oracle fetch) have seemed to not provide much that a tied hash doesn't. And there are currently a ton of, for instance, Text::Blah modules on CPAN--but that doesn't actually mean that they have anything to do with a "Text" namespace--that's not the intention, and most of these modules have nothing to do with each other. That naming is to keep them conceptually organized, not functionally.
I can certainly see having different namespace semantics for different languages, but that doesn't imply arbitrary nesting. That might imply separate "top-level" namespaces, each with its own behavior (so overall, two levels of namespace), or you could just have one-level namespaces, but each with its individualized semantics, or all namespace might be represented by the same type of data structure, which is just traversed differently from different languages. (And I'm not sure that the semantics do differ between languages--given a namespace and a name, there's seemingly only one thing to do.)
And again, I don't so much object to the idea of nested namespaces--I just feel that they'll slow down symbol lookups, without giving us much in return. I'm afraid we're adding complexity we don't need.
Jeff Clites <jcli...@mac.com> wrote: > And again, I don't so much object to the idea of nested namespaces--I > just feel that they'll slow down symbol lookups, without giving us much > in return. I'm afraid we're adding complexity we don't need.
One thing this buys you is that you can have a Perl package:
class Foo::Bar {...}
And in Python, refer to it with Python's syntax:
bar = __Perl.Foo.Bar()
Since both of them boil down to the same thing:
["__Perl"; "Foo"; "Bar"]
-- Brent 'Dax' Royal-Gordon <br...@brentdax.com> Perl and Parrot hacker
There is no cabal. [I currently have a couple Gmail invites--contact me if you're interested.]
> Jeff Clites <jcli...@mac.com> wrote: >> And again, I don't so much object to the idea of nested namespaces--I >> just feel that they'll slow down symbol lookups, without giving us >> much >> in return. I'm afraid we're adding complexity we don't need.
> One thing this buys you is that you can have a Perl package:
> class Foo::Bar {...}
> And in Python, refer to it with Python's syntax:
> bar = __Perl.Foo.Bar()
> Since both of them boil down to the same thing:
> ["__Perl"; "Foo"; "Bar"]
True, but you'd also get this if the Perl and Python compiler authors decided to coordinate and compile down to the same thing, even without namespace nesting. And the Ruby people could decide to do the same, or not, as they prefer. That is, you could get this benefit even if Foo::Bar didn't imply the existence of a Foo namespace. (And frankly, you could even keep the idea a namespace is named by an array of strings, without implying nesting. That wouldn't have the performance impact of actual nesting.)
Jeff Clites writes: > On Sep 12, 2004, at 8:43 PM, Luke Palmer wrote:
> >Jeff Clites writes: > >>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,
> >Other than, um, well, Perl.
> As an implementation detail yes, but I can't think of any Perl code > (except for explicit introspection) which "reveals" this.
Does:
print ${$Foo::{"Bar::"}{baz}}
Count as explicit introspection?
> >No, the lookup is not cascading downwards. It is cascading upwards, > >however, so that in:
> > [ "foo"; "bar"; "baz" ]
> >The [ "foo"; "bar" ] part can be implemented differently. This means > >that Python's namespaces and Perl's namespaces can have different > >semantics. Picture a PythonStash and PerlStash pmc.
> Now it's true that if you think it's really important to tie > namespaces such that you can take over the name resolution for > ["Foo"], then you'd want the former. But I don't see that as really > terribly useful
A debugger.
No, let me restate.
A DEBUGGER!
> --in the examples I've heard of (e.g., turning the namespace lookup > into an Oracle fetch) have seemed to not provide much that a tied hash > doesn't. And there are currently a ton of, for instance, Text::Blah > modules on CPAN--but that doesn't actually mean that they have > anything to do with a "Text" namespace--that's not the intention, and > most of these modules have nothing to do with each other. That naming > is to keep them conceptually organized, not functionally.
Sure. That's not the idea behind the heirarchical namespaces either. A lot of power comes out of being able to treat namespaces as a tree-like data structure (I can actually attest to this: see Class::Closure), as was pointed out before, being able to treat namespaces as a filesystem.
Also, Perl 6's classes will behave more heirarchically:
module Foo;
class Bar {...} my $x = Bar.new; # Actually works, while Bar is Foo::Bar.
I don't know how much that says for my argument though.
On Sunday 12 September 2004 10:08 pm, Jeff Clites wrote: <>
> I'd say that the language-level namespaces should get nice reverse-DNS > names, like ["com.perl.perl5"], or whatever's appropriate.
No, no, no, no. Bad Java programmer! :)
The reverse-DNS namespace sounds great until you realize that not everyone has a domain name. One could imagine some developer whittling away a toy language and hosting off Geocities/Tripod/whatever without having a proper domain name. Or even an programmer who doesn't have an Internet presence for their language at all (lots of academic languages are like this). And what do you do if your domain name changes? Worse, what do you do if someone steals your domain name?
Sun tried using reverse-DNS namespaces for Java, and in my experiance, it causes too many problems for edge cases. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.4 (GNU/Linux)
> On Sunday 12 September 2004 10:08 pm, Jeff Clites wrote: > <> >> I'd say that the language-level namespaces should get nice reverse-DNS >> names, like ["com.perl.perl5"], or whatever's appropriate.
> No, no, no, no. Bad Java programmer! :)
Ha, it's actually one of the few things I like about Java....
> The reverse-DNS namespace sounds great until you realize that not > everyone has > a domain name. One could imagine some developer whittling away a toy > language and hosting off Geocities/Tripod/whatever without having a > proper > domain name. Or even an programmer who doesn't have an Internet > presence for > their language at all (lots of academic languages are like this). And > what > do you do if your domain name changes? Worse, what do you do if > someone > steals your domain name?
> Sun tried using reverse-DNS namespaces for Java, and in my experiance, > it > causes too many problems for edge cases.
Well this issues is, from my perspective, that the only reason anyone needs namespaces at all is that humans want nice short symbol names like "invert()", and order to keep people from conflicting is to have a distinguishing prefix. But that doesn't help unless you can keep the prefixes from clashing, and the only ways to do that are to either have ugly randomly-generated prefixes, which nobody would like, or to explicitly coordinate, via a registry, and DNS is already one such registry. It's not perfect, but all of the above problems are avoidable. (That is, I don't need to have network access at all--I just need to _register_ a domain name, and keep the registration up-to-date. Or, find a domain-owner who's willing to let me user a subdomain--could be along the lines of edu.whatever-university.project-name. And of course this only matters if I'm planning to distribute my software.) That's certainly better than starting with no coordination at all, and forcing people to have to deal with potential conflicts for everything.