On Tue, Nov 01, 2005 at 04:02:04PM -0800, Jonathan Lang wrote:
> True enough; but it needn't be true that d have the same tools
> available to resolve the conflicts that c has.
> 
> There are three ways that a role can deal with a conflict:
> 
> 1. choose one of a set of available methods to call its own.
> 2. create a version of its own.
> 3. pass the buck.
> 
> In the first case, the question is how we define the set of available
> methods: do we make the full hierarchy of ancestors available to the
> role, or do we say that only the immediate parents are available? 

People keep using the word "hierarchy" when talking about roles and I
keep thinking that it is the one word that definitely does NOT apply.
Heirarchies are for classes and inheritance relationships, not roles
and composition.

In my world view, a role that is composed of two other roles has full
view of the methods/attributes defined in the roles that compose it
because the landscape is quite flat. There are no hills and valleys.
When it finally comes down to composing into a class, the class sees
all of the methods/attributes provided by each and every role even the
role inside a role inside a roles.

> Another way to put this would be: should the "DOESA" list be treated
> as public or private?  (My preference: the "DOESA" list should be
> private.  You don't lose any capabilities by doing so, other than the
> capability to access stuff not explicitly declared - a capability that
> roles don't need, and probably shouldn't have.)  If "DOESA" is
> private, then d won't have access to anything from a or b without
> explicitly including them in its own DOESA list.  This seems to be
> restrictive, and it is - but only in the same way that making an
> attribute private is restrictive.

When you say:

        role A { ... }
        role B { ... }
        role C does A does B { ... }
        role D does C { ... }

roles A and B are composed into C at compile time.  If both A and B
define a method foo(), then there is a conflict (immediately, at
compile time) unless you've somehow told perl that it should defer
composition until it's actually composing classes.

What's really at question I think is whether the _default_ is to compose
immediately or to postpone composition until there's a class to compose
into. If you have roles that are never composed into classes, then it
won't matter if there's a conflict as you can't instantiate a role (not
without first turning it into a class). So, on one hand it does make
sense to defer composition until there's a class to compose into. But
it also makes sense to deal with composition conflicts incrementally
too (as roles are composed into other roles).

> The second case is pretty straightforward.

And isomorphic to the first case as it is the resolution to the first
case.

> In the third case, I'd be inclined to say that passing the buck is
> equivalent to creating an undefined version of your own - that is, not
> addressing a conflict involving method x is equivalent to saying
> "method x ($arg) { ... }".  IOW, a class that does a role that passed
> the buck is faced with an "undefined method" complaint if it doesn't
> do something about it, not an "unresolved conflict" complaint.

Nah, the third case is ye olde standard conflict, just perhaps occurring
at a different space+time than had the roles been composed immediately.

-Scott
-- 
Jonathan Scott Duff
[EMAIL PROTECTED]

Reply via email to