=====
Jonathan "Dataweaver" Lang
__________________________________
Do you Yahoo!?
Yahoo! Photos: High-quality 4x6 digital prints for 25¢
http://photos.yahoo.com/ph/print_splash
> -----Original Message-----
> From: Jonathan Lang [mailto:datawe...@yahoo.com]
>
> role A {has Cat $.x;}
> role B {has Dog $.x;}
> class Foo {does Cat; does Dog;}
> my Foo $bar;
> $bar.x; # Is this a Cat or a Dog?
<A12>
If, however, two roles try to introduce a method of the same name (for some
definition of name), then the composition of the class fails, and the
compilation of the program blows sky high--we sincerely hope. It's much
better to catch this kind of error at compile time if you can. And in this
case, you can.
</A12>
Since classes are autogenerating accessors based in data members, it's
doubly reasonable to assume that the same solution will apply: conflict ->
death.
=Austin
From one C6PAN module:
role Dog {
has $.collar;
...
}
From another C6PAN module:
role LawEnforcementOfficer {
method arrest { ... }
...
}
From a third C6PAN module:
class PoliceDog does Dog does LawEnforcementOfficer { ... }
I use PoliceDog in my production code, without a problem. I don't use
the collar attribute (it's unimportant in my application).
The author of the LawEnforcementOfficer role does an upgrade that fixes
an important bug but also.....
role LawEnforcementOfficer {
method arrest { ... }
has $.collar; # for holding most recently arrested
...
}
So when my program fails to compile, who do I blame? How do I fix it
quickly, preferrably without creating local branches of the C6PAN modules?
>
> =Austin
>
> From one C6PAN module:
>
> role Dog {
> has $.collar;
> ...
> }
> From a third C6PAN module:
>
> class PoliceDog does Dog does LawEnforcementOfficer { ... }
> role LawEnforcementOfficer {
> method arrest { ... }
> has $.collar; # for holding most recently arrested
> ...
> }
>
> So when my program fails to compile, who do I blame?
Whoever didn't read the documentation for the appropriate roles. :)
> How do I fix it
> quickly, preferrably without creating local branches of the C6PAN modules?
* Add a disambiguatey method to PoliceDog that dispatches
appropriately. (Insert handwavey "well you *could* do it this way or
you *might* do it that way.")
* Force the loading of a specific version of LawEnforcementOfficer.
-- c
> * Add a disambiguatey method to PoliceDog that dispatches
> appropriately. (Insert handwavey "well you *could* do it this way or
> you *might* do it that way.")
I agree, but given that the average user should probably not have to
interact with the dispatching system just to say "my class uses class
a's foo, not class b's foo", can I suggest:
class a { method foo {...} }
class b { method foo {...} }
class c { does a; does b but a.foo; }
the "but" disarms the compilation failure that A12 introduced, but only
for that method. Every time you have such a conflict, you will have to
disarm in this way. What MIGHT be a problem is:
class c { does a but b.bar; does b but a.foo; }
which requires the compiler to accept b.bar even though it has not yet
seen the "does b". You could assert the other way around:
class c { does a for <<bar baz>>; does b for <<foo biz>>; }
which is kind of nifty looking, but some may blanch at the dual meaning
for "for"....
--
Aaron Sherman <a...@ajs.com>
Senior Systems Engineer and Toolsmith
"It's the sound of a satellite saying, 'get me down!'" -Shriekback
Funny how similar that is to
class c { does a handles <<bar baz>>; does b handles <<foo biz>>; }
--
Brent "Dax" Royal-Gordon <br...@brentdax.com>
Perl and Parrot hacker
Oceania has always been at war with Eastasia.
> Funny how similar that is to
>
> class c { does a handles <<bar baz>>; does b handles <<foo biz>>; }
In "Relationship to Roles" A12 makes the point that delegation and roles
are not the same thing.
To tie them together with C<handles> MIGHT be wise and might not. I'll
have to think about that and see what others post on the topic.
I have not read the delegation section enough, either... something I
need to fix. It certainly seems powerful, as it merges the "has" and
"is" relationship in some very interesting ways, and eliminates some
overhead that would appear in many classes that would have otherwise had
to re-dispatch methods pertaining to their encapsulees.
> -----Original Message-----
> From: Aaron Sherman [mailto:a...@ajs.com]
>
> On Fri, 2004-04-23 at 11:44, Brent 'Dax' Royal-Gordon wrote:
> > Aaron Sherman wrote:
>
> > > class c { does a for <<bar baz>>; does b for <<foo biz>>; }
>
> > Funny how similar that is to
> >
> > class c { does a handles <<bar baz>>; does b handles <<foo biz>>; }
>
> In "Relationship to Roles" A12 makes the point that delegation and roles
> are not the same thing.
>
> To tie them together with C<handles> MIGHT be wise and might not. I'll
> have to think about that and see what others post on the topic.
This seems good at first blush:
"handles" means "when I'm asked to do this, it is taken care of by this
other"
That seems like a good disambiguation marker, too:
class Trog does Tree does Dog {...}
# error: conflicting 'bark' methods
class Trog
is PersistentObject
handles «meta dispatch SERIALIZE»
does Tree
handles «bark»
does Dog
{...}
=Austin
> : does Tree
> : handles «bark»
> : does Dog
> That works in the case of an explicitly named method, since that
> effectively makes .bark a method in the current class. It would not
> work for a wildcard delegation though, unless Dog were specifically
> marked not to handle .bark.
That's fine.
I would expect wildcard delegation not to care about method conflicts at
all, since what's being done is, by its nature, much more dynamic
anyway.
> -----Original Message-----
> From: Larry Wall [mailto:la...@wall.org]
>
> On Fri, Apr 23, 2004 at 01:05:21PM -0400, Austin Hastings wrote:
> : That seems like a good disambiguation marker, too:
> :
> : class Trog does Tree does Dog {...}
> :
> : # error: conflicting 'bark' methods
> :
> : class Trog
> : is PersistentObject
> : handles «meta dispatch SERIALIZE»
> : does Tree
> : handles «bark»
> : does Dog
> : {...}
>
> That works in the case of an explicitly named method, since that
> effectively makes .bark a method in the current class. It would not
> work for a wildcard delegation though, unless Dog were specifically
> marked not to handle .bark.
>
Junctions to the rescue!
class Trog
does Tree
handles «bark»
does Dog
handles none«bark»
{...}
=Austin
That works in the case of an explicitly named method, since that
effectively makes .bark a method in the current class. It would not
work for a wildcard delegation though, unless Dog were specifically
marked not to handle .bark.
Larry
> I would expect wildcard delegation not to care about method conflicts at
> all, since what's being done is, by its nature, much more dynamic
> anyway.
I misunderstood roles when I said this... I now get why this is a
problem, sorry.
Note that the problem extends past accessors: a role's methods can access
its attributes directly. So:
role A {has Cat $.x; method m1 {return $.x;};}
role B {has Dog $.x; method m2 {return $.x;};}
class Foo {does Cat; does Dog;}
my Foo $bar;
$bar.m1; # returns $A::x, right?
$bar.m2; # returns $B::x, right?
If the two $.x's are completely equivelent, you end up with redundant data
storage.
Then again, this may be more of a quirk than a problem...
Actually, it'd blow up at composition time anyway, since there's a default
readonly accessor for each $.x variable.
:
: Then again, this may be more of a quirk than a problem...
I'd like to think so. But then, I thought that about a lot of Perl 5 OO...
Larry
I'd think, assuming roles are allowed to add attributes (and, if so,
I'd argue "what's the difference between a class and a role, then?"
but someone'd hit me), that the attribute would be role-specific. In
the above case you'd have two separate attributes.
--
Dan
--------------------------------------"it's like this"-------------------
Dan Sugalski even samurai
d...@sidhe.org have teddy bears and even
teddy bears get drunk
OK; so add "method x {...};" to class Foo to keep it from blowing up. Foo
still has to track two scalars internally.
Actually, it's worse than that: let's add "has Elephant $.x;" to Foo
instead. Since class trumps role, does $bar.m1 now work with an Elephant,
or does it still work with a Cat?
I think the attributes have to be considered to belong primarily to
the role, and a role that references one of its own attributes knows
that it is doing so to the exclusion of any other similarly named
attribute in the class or in a different role. Accessing a role's
attribute from within a class or another role should really only work
as a fallback, if at all. I think people should be encouraged to use
the methods where performance is not at a premium. Most of these will
be private attributes in any event, so using the :method doesn't have
to do virtual dispatch. But private attributes also belong primarily
to the role, and only secondarily to the class or other roles. However,
the roles do implicitly trust each other by virtue of being composed
into the same class, so they can see each other's private methods.
Note that this means you can write roles that are only meaningful
when composed into a class with certain other roles or methods, and
cannot be used as mixins, since a mixin would never see the private
methods from an overridden base class. The only way to do it as a
mixin is to have a composite role containing all the other roles, and
then mix that one role in all at once. (Which is probably what you
want to do anyway for efficiency, when you know you have to mix
in multiple roles.)
Larry