Ovid wrote: > The only way to handle this appears to be renaming one of the x() > methods and trying to track down all code which relies on it and > changing it. This essentially violates the problem we're trying to > solve with traits, er, roles. > > In short, under the original traits model, you have roles you can't > compose together. The paper argues that in languages which have > "public" and "private" methods, that the composing class is allowed to > decide which x() method it needs (if any) and that it can *freeze* the > other x() method. That is to say, the x() in question would become > private and statically bound to the invocants to ensure that they're > always calling the correct x(). > > How would Perl 6 approach this issue?
The fundamental problem is that there are times when you need both versions of a given method to be available, but you don't want to rename either of them. This leads to a namespace clash. The initial possibility that springs to mind would be to use longnames to disambiguate between the two options - specifically, by means of the invocant: role T1 { method foo() } role T2 { method foo() } class C does T1 does T2 { method foo(T1 $self:) { $self.T1::foo() } method foo(T2 $self:) { $self.T2::foo() } } ...or something to that effect. You'd still have a disambiguation issue, in that you'd somehow need to specify which "hat" an object of class C is wearing when you try to call the method. (I like this approach because it requires you to explicitly identify that the class is deferring the disambiguation, rather than having it silently occur behind the scenes.) Much of this could be handled implicitly, by means of which role was requested when the object was passed into the current block: sub bar (T1 $x) { ... } sub baz (T2 $x) { ... } my C $x; bar $x; Since "bar" is expecting an object that does T1, code within bar should resolve the ambiguity involving foo in favor of foo:(T1:) - that is, within the lexical scope of sub bar, $x is wearing its T1 hat. Ditto with baz and T2. In other cases, there may be no way to implicitly disambiguate. In those cases, there would need to be an explicit way to decide which hat the object is wearing. My gut instinct would be to use the same syntax as is used to coerce an object into a particular class, but with a role name instead of a class name. It differs from coercion in that it wouldn't actually change the underlying object; all it would do would be to decide which role to favor when resolving disputes of this sort. In short, resolve the dilemma by allowing the class the option of deferring the disambiguation until the method is called, and then to try to resolve it first by means of the overall context in which the call is made. This "Schrodinger's method" approach doesn't fix everything; but I suspect that it should usefully handle the majority of problems that arise. -- Jonathan "Dataweaver" Lang