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