Hello all,
I have a question about method conflict resolution works for roles,
and I cannot seem to find this in any of the Apoc/Syn documents.
Here is the basic issue:
role Foo {
method foo { ... }
method bar { ... } # we will use this later :)
}
role Bar {
method foo { ... }
}
role FooBar {
does Foo;
does Bar;
}
Now, at this point we have a method conflict in suspension since
(according to A/S-12) method conflicts do not throw an error until a
role is composed into a class. This means that when I do this:
class MyClass does FooBar {}
an exception is thrown. Unless of course MyClass has a &foo method,
which will disambiguate the conflict. My question then is, can FooBar
(the role) disambiguate the &foo conflict?
role FooBar {
does Foo;
does Bar;
method foo { ... }
}
Now, on the surface this seems obvious, of course the FooBar role
should be able to disambiguate. However, when we expand the example
other issues show up.
role Baz {
does Foo;
}
class MyClass2 does FooBar does Baz {} # Will this die?
Now, since MyClass2 actually does Foo twice, does that mean &bar
creates a conflcit? Since &bar would be found through FooBar and Baz.
I would think the answer here would be no, and that we would build
some kind of unique list of roles so as to avoid repeated consumption
like this.
But thats not all, we have a potential problem with &foo again. Baz
will provide &foo from Foo, but FooBar will provide it's own &foo
(which we used to disambiguate). So our disambiguation is not
ambiguated again.
/ Possible Solutions /
A (deceptively) simple solution to this is that MyClass2 needs to
disambiguate. But this means that our roles are not really black
boxes anymore. In order to properly disambiguate this we need to know
where all the &foo methods are coming from (Foo, Bar and FooBar), and
potentially what is inside these &foo methods (especially in the case
of FooBar since it is attempting to disambiguate, it's behavior could
be very specific). It probably would also become important to know
what other methods &foo interacts with since we potentially have 3
different expected versions of &foo.
In the end, we will have probably looked inside every method defined
in Foo, Bar, FooBar and Baz in order to properly write MyClass2.
IMHO, this is sort of defeating the usefulness of roles at this point.
Another simple (but maybe slightly unintuitive) solution would be to
not allow roles to disambiguate at all.
(Quick side note: Doing this means that roles like FooBar (which
carry with them a "suspended" conflict) would be restricted in what
types of behaviors they can provide. Basically they would only be
able to provide new behaviors which are unrelated to those provided
by Foo and Bar. If it were to try to use methods from Foo or Bar, it
would really end up needing to disambiguate.)
This actually makes MyClass2 somewhat simpler now, since it only need
to disambiguate between &foo from Foo, and &foo from Bar. Of course
this is only marginally better, since you would still need to look
inside all the methods of Foo, Bar, FooBar and Baz to see how &foo is
being used so you could disambiguate properly.
...
So what do you all think??
Stevan