Re: Packages, Modules and Classes

2005-09-09 Thread Larry Wall
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

2005-09-09 Thread Larry Wall
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

2005-09-08 Thread Larry Wall
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

2005-09-08 Thread Stevan Little

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

2005-09-08 Thread Larry Wall
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

2005-09-08 Thread Stevan Little

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

2005-09-07 Thread Larry Wall
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 Foobar, presumably with
extra canonicalized key info for long names.

Larry


Re: Packages, Modules and Classes

2005-09-07 Thread Larry Wall
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 Foobar, 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 Foobar 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 Foobar and Foo.bar.  But for now
we've got subs and/or methods in the same namespace.

Larry


Re: Packages, Modules and Classes

2005-09-07 Thread Stevan Little

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

2005-09-07 Thread Larry Wall
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

2005-09-07 Thread Stevan Little

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



Packages, Modules and Classes

2005-09-06 Thread Stevan Little

Hey all,

I recently added Package and Module into the MetaModel (2.0) so that

   Package is an Object
   Module is a Package
   Class is a Module

as mentioned here 
http://article.gmane.org/gmane.comp.lang.perl.perl6.language/4599. 
Currently Packages have names and Modules add version and authority 
information, but I have nothing yet in place to represent package 
symbol tables. Which brings me to my questions.


I assume that each symbol table entry has the following slots; SCALAR, 
ARRAY, HASH, SUB, METH. 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.


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. 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?

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)?


Thanks,

Stevan