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




Reply via email to