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

Reply via email to