Re: Packages, Modules and Classes
On Fri, Sep 09, 2005 at 08:46:06AM -0700, Larry Wall wrote: : If these are really postfix operators, then we can also write : : Foo .::{} : Foo .::<> : Foo .::() But I don't think they can really be postfix. At least, ::() isn't, since $Foo .::($bar) would not be the same as we defined $Foo::($bar) to be. That is, ::() is really an interpolating syntax in the current design. Maybe that needs to be broken. I dunno. My hemoglobin to caffeine ratio is still too high. Larry
Re: Packages, Modules and Classes
On Thu, Sep 08, 2005 at 07:41:52PM -0400, Stevan Little wrote: : So it would be Foo::.keys() then? : : Would this be possible? The more I think about it, the more I'm leaning toword postfix operators ::{} and ::<>, essentially in same syntactic niche as ::(). Which means you'd have to write that as Foo::{}.keys() If these are really postfix operators, then we can also write Foo .::{} Foo .::<> Foo .::() Postfix operators are expected in operator position. Note that ::{$ref} in term position actually requires a hard $ref inside instead of a key, so that's a slight inconsistency. But probably one we can live with. : my $pkg = Foo::; : # or maybe this ... : my $pkg = Foo<::>; If we went this way, that'd be: my $stash = Foo::{}; : Would $pkg be an instance of the Package class? I don't think so. I think that ::{} and ::<> would basically return the hash attribute in the Package object. So it's probably just Hash, or maybe Stash. : I would assume given : this code: : : package Foo { : ... : package Foo::Bar { : ... : } : } : : I can do this: : : my $pkg = Foo::{'::Bar'} : : And get back some kind of Package reference of some kind. Yes, that gives you the package. But my $stash = Foo::{'::Bar'}::{} would just give you the stash of the package. By the way, you don't have to write your inner package as Foo::Bar, since package/module/class declarations now assume "our". (File-scoped classes defaulting to * because that's the current package down to the first declaration in the file. Then the first declaration either switches explicitly to some package/module/class, or a "use v6" thingie implicitly switches to Main, or we're still in Perl 5's main.) : Do we even have first class packages? Sure. They should be as first class as modules or classes. But let us now say that a package ISn't Hash and DOESn't Hash. It merely HAS a private stash attribute that does Hash, which is made accessible (at least the public bits) via ::{}, ::<>, and ::(). Those operators can by default hide access to private ._fnord methods, for instance. And ::{}.keys would not tell you about private methods. Hmm, that seems a little difficult to implement. But hey, now that we've decoupled the stash from *being* the package object by making it an attribute, why don't we say that any ._fnordish things just get stuffed into a *different* stash attribute, and the ::{} can simply return the public stash without having to do any filtering. I think that's a lot cleaner. Larry
Re: Packages, Modules and Classes
Larry, On Sep 8, 2005, at 5:07 PM, Larry Wall wrote: On Thu, Sep 08, 2005 at 04:52:52PM -0400, Stevan Little wrote: : But what if I want to do this? : : class Foo { : my %:stuff; : method keys (Class $c:) { : %:stuff.keys(); : } : } : : How can I get at my namespace now? How would I disambiguiate that call? : Doing something like Foo.Package::keys() seems to me to be exposing too : much of the meta-level (the Package class). : : I can see lots of potential conflict between class methods and methods : to access the contents of a namespace (methods defined in the Hash role : I assume). This means that Foo is getting even more and more magical. : It's now a type annotation, a special undef value, the invocant in : class methods and the "gatekeeper" of the namespace. Well, like I said, we can require the extra :: in cases of ambiguity. It's really only the misplaced sigil I'm trying to get rid of. So it would be Foo::.keys() then? Would this be possible? my $pkg = Foo::; # or maybe this ... my $pkg = Foo<::>; Would $pkg be an instance of the Package class? I would assume given this code: package Foo { ... package Foo::Bar { ... } } I can do this: my $pkg = Foo::{'::Bar'} And get back some kind of Package reference of some kind. Do we even have first class packages? h Stevan
Re: Packages, Modules and Classes
On Thu, Sep 08, 2005 at 04:52:52PM -0400, Stevan Little wrote: : But what if I want to do this? : : class Foo { : my %:stuff; : method keys (Class $c:) { : %:stuff.keys(); : } : } : : How can I get at my namespace now? How would I disambiguiate that call? : Doing something like Foo.Package::keys() seems to me to be exposing too : much of the meta-level (the Package class). : : I can see lots of potential conflict between class methods and methods : to access the contents of a namespace (methods defined in the Hash role : I assume). This means that Foo is getting even more and more magical. : It's now a type annotation, a special undef value, the invocant in : class methods and the "gatekeeper" of the namespace. Well, like I said, we can require the extra :: in cases of ambiguity. It's really only the misplaced sigil I'm trying to get rid of. Larry
Re: Packages, Modules and Classes
Larry, On Sep 8, 2005, at 2:30 PM, Larry Wall wrote: On Wed, Sep 07, 2005 at 03:00:29PM -0400, Stevan Little wrote: : Also, is there anyway to iterate over the keys in the namespace? The : old way would be to do something like keys(%Foo::). Is something like : this possible with the new way? Sure, it's still just a hash, basically, so Foo.keys() works fine. All we've changed is that we've removed a special syntactic case by allowing a type/package object to pretend to be a hash when used that way, just as we allow it to pretend to be an undef when used as an instance. Tagmemics strikes again... But what if I want to do this? class Foo { my %:stuff; method keys (Class $c:) { %:stuff.keys(); } } How can I get at my namespace now? How would I disambiguiate that call? Doing something like Foo.Package::keys() seems to me to be exposing too much of the meta-level (the Package class). I can see lots of potential conflict between class methods and methods to access the contents of a namespace (methods defined in the Hash role I assume). This means that Foo is getting even more and more magical. It's now a type annotation, a special undef value, the invocant in class methods and the "gatekeeper" of the namespace. Stevan
Re: Packages, Modules and Classes
On Wed, Sep 07, 2005 at 03:00:29PM -0400, Stevan Little wrote: : If methods and subs are in the same namespace, and both have the & : sigil, what about instance attributes and class attributes? Is this : legal? : : class Foo { : my $.bar; : has $.bar; : } : : Part of me thinks that it should be since my $.bar is an attribute of : the Foo class, and has $.bar is an attribute of instances of Foo. I don't think that should be any more legal than { my $foo; our $foo; } since both declarations are trying to install the same symbol in a scope regardless of the actual scope/lifetime of the variable in question. The difference is that with the latter, the collision is in the lexical scope, while in the former, the collision is in the package's method name space. The problem is you're making two .bar accessors in the same scope, even if the things being accessed are in different places. It's also a problem under my current view that Foo (the non-meta class) is primarily just the undefined prototype instance, in which case you don't want to make artificial distinctions between the type of Foo itself and the type of its instances. So I think that if .can is true for an instance method it should also be true of the class method, even if it would fail when used on the class object (because it's undefined, not because it's a different type). This fits with the policy that we want to be able to use class names to reason about class behavior generically even in the absence of an actual instance. Foo.can('bar') needs to be true regardless of whether you said "my" or "has". : Also, is there anyway to iterate over the keys in the namespace? The : old way would be to do something like keys(%Foo::). Is something like : this possible with the new way? Sure, it's still just a hash, basically, so Foo.keys() works fine. All we've changed is that we've removed a special syntactic case by allowing a type/package object to pretend to be a hash when used that way, just as we allow it to pretend to be an undef when used as an instance. Tagmemics strikes again... Of course, this is not entirely free, insofar as the Hash role has to figure out when it's being composed into a class, and pick an entirely different behavior when used as a class name than when used as an instance of the class. That is, Foo{$x} wants to do a symbol table lookup, while (new Foo){$x} has to access the Hash interface of the instance. But still think I'd rather hide the semantic fudge down there than bake it into special syntax, even though it means being a wee bit inconsistent about the type relationship of Foo and (new Foo). Or if that ends up causing too much indigestion, we could still back off to a Foo::{$x} syntax without requiring % on the front. After all, the main point of the change is to get rid of the sigil on the front of things like $CALLER::_ so that we end up with CALLER<$_> instead. So CALLER::<$_> wouldn't be all that bad if we decide the bare package name is too ambiguous in its semantics. Then we'd probably see things like ::($pkg)::<$var> ::($pkg)::{$varname} Hmm, unless we actually spring for infix:<::> to get $pkg :: '$var' $pkg :: $varname But I think that makes symbolic references a little too easy to use, and a little too hard to spot. Though I suppose that's no worse than the current proposal allowing $pkg<$var> $pkg{$varname} Maybe what we really have is a class of *postfix* operators that all begin with ::, as in ::(...) ::<...> ::{...} Basically steal the :: from the old %Foo:: syntax, and analyze it the other way. Then a name is simply not allowed to end with ::. Postfix operators are recognized where an operator is expected. But if a term can start with ::(), maybe it can start with ::<> or ::{} as well. Not quite sure if that makes sense. We could make it mean something. Doubtless term ::<$foo> should mean the same as $foo though. Term ::{$varname} is probably just MY::{$varname}, and also likely to be confused with ::($sym). So that approach doesn't really buy us much. So let's just try to make the simple Foo<$var> form stick for now, and back off later if forced to. Larry
Re: Packages, Modules and Classes
Larry, On Sep 7, 2005, at 12:45 PM, Larry Wall wrote: : >All sigils and twigils are part of the key to the symbol table, so it's : >now just : > : >Foo<$.baz> : : What would Foo<$.baz> return though (assuming Foo is a class)? It : cannot return a value since it is an instance specific value. Foo<@baz> is not a value either, but a container. I would say that Foo<$.baz> returns a generic container that happens not to work without an extra instance argument to say which chunk of data to map the container metainfo onto. : Should it return some kind of meta-object? Yes. If methods and subs are in the same namespace, and both have the & sigil, what about instance attributes and class attributes? Is this legal? class Foo { my $.bar; has $.bar; } Part of me thinks that it should be since my $.bar is an attribute of the Foo class, and has $.bar is an attribute of instances of Foo. Also, is there anyway to iterate over the keys in the namespace? The old way would be to do something like keys(%Foo::). Is something like this possible with the new way? Thanks, Stevan
Re: Packages, Modules and Classes
On Wed, Sep 07, 2005 at 12:27:20PM -0400, Stevan Little wrote: : How do I differentiate a method from a sub? Wouldn't they both have the : & sigil? Yes, as it currently stands, you can only tell that by introspection. : >: class Foo; : >: has $.baz; : >: method bar { ... } : >: : >: Can I get to $.baz? If I can, what will I get? : > : >All sigils and twigils are part of the key to the symbol table, so it's : >now just : > : >Foo<$.baz> : : What would Foo<$.baz> return though (assuming Foo is a class)? It : cannot return a value since it is an instance specific value. Foo<@baz> is not a value either, but a container. I would say that Foo<$.baz> returns a generic container that happens not to work without an extra instance argument to say which chunk of data to map the container metainfo onto. : Should it return some kind of meta-object? Yes. :Or possibly the default value specified (if one is specified)? No, symbol tables don't hold values. (We once thought about making the attribute return the default value within class methods (in fact the Apocalypse espouses that, if I recall) but we eventually decided that it was a confusing idea.) : Can this value be written too? Only via introspection. : If so, how does that affect things? Doesn't, since you can't. : Also would/should this work: : : $iFoo<$.baz> Yes, but... : As a means of breaking the opaque instance data structure. (I for one, : vote no on that). It would still get you the metacontainer, which these days still represents an virtual call and thus doesn't break encapsulation. The name of the non-virtual storage for $.baz is currently $._baz (with a private ._baz() accessor akin to the old .:baz() accessor), and we presumably take steps to prevent people from breaking any "_" encapsulation trivially. (The debugger needs to get at the info, of course, which basically means anyone can if they pretend to be the debugger, but we don't have to make it easy...) Larry
Re: Packages, Modules and Classes
Larry, On Sep 7, 2005, at 11:46 AM, Larry Wall wrote: : I base this off the AUTO* hooks described in : S10. I assume too that the METH slot is only valid for Classes, and not : appropriate for Packages and Modules. All those entries are based on the notion of intuiting from the first character of the variable name within the symbol table, not from having separate typeglobbish slots within each symbol. How do I differentiate a method from a sub? Wouldn't they both have the & sigil? : class Foo; : has $.baz; : method bar { ... } : : Can I get to $.baz? If I can, what will I get? All sigils and twigils are part of the key to the symbol table, so it's now just Foo<$.baz> What would Foo<$.baz> return though (assuming Foo is a class)? It cannot return a value since it is an instance specific value. Should it return some kind of meta-object? Or possibly the default value specified (if one is specified)? Can this value be written too? If so, how does that affect things? Also would/should this work: $iFoo<$.baz> As a means of breaking the opaque instance data structure. (I for one, vote no on that). - Stevan
Re: Packages, Modules and Classes
On Wed, Sep 07, 2005 at 08:46:24AM -0700, Larry Wall wrote: : No special {FOO} subscripts, so the question doesn't arise. To the : symbol table all blocks are stored as Foo<&bar>, presumably with : extra canonicalized key info for "long" names. Actually, we might well omit the '&' on Code objects for better interoperability with other languages, unless we name mangle it. (Might need to name-mangle the key of Foo<::Bar> in any event, so maybe Foo<&bar> isn't any different in that respect when other languages want to look up the .bar method. Come to think of it, Perl 6 usually wants to look it up without the & too. :-) If for some reason we decided to allow a sub and a method of the same name, I suppose we could make them Foo<&bar> and Foo<.bar>. But for now we've got subs and/or methods in the same namespace. Larry
Re: Packages, Modules and Classes
On Tue, Sep 06, 2005 at 02:04:00PM -0400, Stevan Little wrote: : I assume that each symbol table entry has the following slots; SCALAR, : ARRAY, HASH, SUB, METH. Nope, typeglobs are dead, dead, dead, dead, and dead, not necessariy in that order. : I base this off the AUTO* hooks described in : S10. I assume too that the METH slot is only valid for Classes, and not : appropriate for Packages and Modules. All those entries are based on the notion of intuiting from the first character of the variable name within the symbol table, not from having separate typeglobbish slots within each symbol. : This would mean that given this code: : : package Foo; : our $baz; : sub bar { ... } : : %Foo::{'bar'}{SUB} is a ref to the &bar sub, and %Foo::{'baz'}{SCALAR} : is a ref to the scalar $baz. That syntax is also dead, including the %Foo:: part of it. If you'll look at the most recent S2 from http://svn.perl.org/perl6/doc/trunk/design/syn/S02.pod (the dev.perl.org web pages are out of date), you'll find: To do direct lookup in a package's symbol table without scanning, treat the package name as a hash: Foo::Bar{'&baz'}# same as &Foo::Bar::baz GLOBAL<$IN> # Same as $*IN Foo<::Bar><::Baz> # same as Foo::Bar::Baz Unlike C<::()> symbolic references, this does not parse the argument for C<::>, nor does it initiate a namespace scan from that initial point. : The same, I would assume, would apply for : Modules, so that: : : module Foo; : our $baz; : sub bar { ... } : : is pretty much interchangable with the first example. But I think it's : a little trickier when we get to Classes. Given this code: : : class Foo; : our $baz; : sub bar { ... } : : I would expect it to behave just as it does for a Package or Module. : But when we start to introduce methods and attributes, I am unsure of : how things will work. : : class Foo; : has $.baz; : method bar { ... } : : Can I get to $.baz? If I can, what will I get? All sigils and twigils are part of the key to the symbol table, so it's now just Foo<$.baz> : I expect that %Foo::{'bar'}{METH} will give me a method ref, but what : happens when I try to store something in it? Does that perform some : kind of meta-model actions (Foo.meta.change_method(...) or somesuch)? : What if I delete the symbol table entry, what happens then (more : meta-trickery)? No special {FOO} subscripts, so the question doesn't arise. To the symbol table all blocks are stored as Foo<&bar>, presumably with extra canonicalized key info for "long" names. Larry