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

Reply via email to