On Mon, Jul 18, 2005 at 03:34:36PM +1200, Sam Vilain wrote:
: Say I make an "accessor" method for an attribute that doesn't really
: 'exist'.
: 
: For instance, a good example of this is the "month_0" vs "month"
: properties on a date object; I want to make both look equivalent as
: real properties, but without the users of the class knowing which
: one is the "real" one.
: 
: Users of the class includes people subclassing the class, so to them
: they need to be able to use $.month_0 and $.month, even though there
: is no "has $.month_0" declared in the Class implementation, only
: "has $.month".

We thought about defining the attribute variables that way,
but decided that it would be clearer if they only ever refer to
real attributes declared in the current class.  Outside the class,
including in subclasses, you have to use the accessors, so it's always
$self.month_0 and $self.month, however you end up spelling $self...

: So, is $.month just shorthand for $?SELF.month, which happens to be
: optimised away to a variable access in the common case where the
: "method month" isn't defined, or has a sufficiently simple "is
: accessor" trait in its declaration?

Nope.  $.month is actually a primitive form that can't be expressed in
terms of method calls in the absence of knowledge about the internals
of the object's representation, which is (by default) opaque in Perl 6.
Another difference is that $.month is never virtual, while $?SELF.month
is always virtual.

: And that, in turn, $:month is actually $?SELF.(":month"), where
: ":month" is an alias for the submethod called "month".

That seems divergent in several different ways.  Like $.month, $:month
is also a primitive form that is never virtual.  Unlike $.month,
it does not actually generate a virtual accessor method at all.
It essentially generates a private subroutine accessor that you
can call as as $?SELF.:foo(), which is syntactic sugar for $:foo
only within the class and trusted classes.  Apart from that there
is *no* access to the attribute from outside the class whatsoever.
This private accessor is not at all related to submethods, which have
restricted inheritance but are otherwise callable from anywhere.
There is no aliasing from ":month" to "month".  That colon is very
much a part of the name of the private method, so you can have

    method :foo {...}   # private foo method
    method foo {...}    # public foo method

and there is no conflict at all.  That's because we don't want the
existence or non-existence of :foo to ever change the external
interface.

In contrast, this is illegal:

    method foo {...}    # public method foo
    submethod foo {...} # public submethod foo

because you're trying to define two methods of the same name.

: After all, we want Roles used by Classes to have access to this virtual
: attribute coolness, too.

Roles have exactly the same virtual attribute access as classes, via
methods.  A role that is trying to access both the physical attribute
and the virtual attribute is likely to be mixing two different roles
as one role, and should probably be split.  Keeping the distinction
between $.foo and $self.foo helps enforce that.  But I suspect most of
the coolness you want to do can be just as easily expressed in the
$self.foo form.  And the part you can't is probably not so cool.

: These simple definitions should make all sorts of OO tricks possible,
: and reduces the definition of Classes to one that is purely
: functional (ie, state is just a set of functions too).

One can certainly rewrite $.foo and $:foo in terms of lower level
functional primitives, but we must be careful not to confuse those
with higher-level virtual method calls.  Otherwise we are mixing OO
interface with OO implementation, and we've already discovered in
Perl 5 that that's a Bad Idea.  Interfaces between organisms are
cleaner when their innards stay in and their outtards stay out.

Larry

Reply via email to