Jonathan Worthington wrote:
> Ovid wrote:
>>
>> I was asking the special case where:
>>
>> 1. A class consumes two (or more) roles
>> 2. Each roles provides a method with an identical signature
>> 3. The methods are not equivalent and neither role can rely on the other's
>> method
>>
>>  With that, you have roles which cannot be composed. You must rewrite one
>> (bad if you don't own it), or omit one..
>
> When a role is composed into a class, it does quite literally become as if
> it were declared within the class itself (appears directly in the methods
> list), but equally does not lose its lexical scoping relationship with the
> role it was declared in either. Would it help to say that when a method
> declared within a role invokes another method, then we first search the
> methods within that role's lexical scope? Therefore:
>
> role Drinking {
>   method buy_beer() {
>       self.go_to_bar();
>       ...
>   }
>   method go_to_bar() {
>       ...
>   }
> }
>
> role Gymnastics {
>   method go_to_bar() {
>   }
> }
>
> class DrunkGymnast does Drinking does Gymnastics {
>   method go_to_bar() {
>       # something to resolve the conflict here
>   }
> }
>
> This way, the method "buy_beer" will always consider methods in its lexical
> scope first and thus find the role's "go_to_bar" rather than the one in the
> class. Of course, if the role's lexical scope had no methods of that name
> declared within it we'd go elsewhere.

This is close to what I've been suggesting in terms of checking which
hat the object is wearing (or, alternately, which role it is
performing).  The main difference is that the final say _must_ be
given to the class, because only the class knows enough about the
implementation to be sure to do the right thing.  For instance, what
if you want the DrunkGymnast who goes to the bar in the Drinking sense
to automatically be given a citation for doing so?  class DrunkGymnast
is the place where this issue must be addressed.  Or worse: if you
have her go_to_bar in the Drinking sense, you set a flag that
indicates that she's drunk; and if you have her go_to_bar in the
Gymnastics sense while she's drunk, the call should fail.  This can
only be done if you can define two distinct go_to_bar methods within
the class, because Perl no longer has a "want" mechanism that would
allow one method to handle both cases.

This is where my proposal for disambiguating the two of them according
to the invocant comes in.  Ovid need not be right about his statement
#2: while the two methods have the same short names (e.g.,
"go_to_bar") and accept the same arguments (e.g., none), they don't
necessarily have the same signatures, because they can use the
invocant's type to address the "in the Drinking sense" and "in the
Gymnastics sense" concept that I was using in the previous paragraph.
As such, the two methods can have the same names and the same
parameter lists, but still have different signatures (and thus
different long-names): "go_to_bar:(Drinking:)" and
"go_to_bar:(Gymnastics:)".

The trick would lie in making the compiler smart enough to DWIM in
most cases (by figuring out for itself which sense you mean), and in
providing an easy-to-use means of explicitly choosing a sense to cover
the remaining cases.

I have some more thoughts on this; but I'm on a time crunch at the
moment, and would really like to get some feedback on the above before
proceeding further: have I missed anything in my reasoning?

-- 
Jonathan "Dataweaver" Lang

Reply via email to