Trey Harris wrote:
In a message dated Fri, 13 Oct 2006, Jonathan Lang writes:
> Since Baz does both Foo and Bar, you cannot use type-checking to
> resolve this dilemma.

Why not?  Why shouldn't this work:

   my Foo $obj1 = getBaz();  # object is a Baz
   $obj1.baz();              # Foo::baz is called

   my Bar $obj2 = getBaz();  # object is a Baz
   $obj2.baz();              # Bar::baz is called

   my Baz $obj3 = getBaz();  # object is a Baz
   $obj3.baz();              # Depends on Bob's implementation of ::Baz

The first two cases would also depend on Bob's implementation of Baz:
for dispatch purposes (single or multiple), the class' method takes
precedence over the role's method.  This is there so that the class
can resolve disputes between roles, and so that the class can refine
role behavior as appropriate.  Short-cirtuiting past the class' method
eliminates the latter option.

Also, even if the first two cases did work as you say, how would I get
$obj1 to call Bar::baz when it needs to?

All three objects happen to be Baz's, yes.  But the client code doesn't
see them that way; the first snippet wants a Foo, the second wants a Bar.
They should get what they expect, or Baz can't be said to "do" either.

In principle, I agree; that's how it _should_ work.  I'm pointing out
that that's not how things work in practice according to the current
documentation.  (Well, 99% of the time they do; that's why this is an
edge case.)  If the first snippet asks for a Foo and gets handed a
Baz, it receives a Baz - and then (ideally) works with those portions
of Baz that behave like Foo.  The problem is that roles that can be
used together in theory but which conflict in practice can lead to
cases where the snippet _thinks_ it's working with the Foo-like
portions when it really isn't.

If methods are entirely dispatched *by name* ("duck typing"), then I
agree, we have a problem.  But Perl 6 supposedly supports a) multiple
inheritance, b) multiple dispatch, c) traits, and d) DBC.  I believe the
union of those requirements means that methods must be dispatched in a
more sophisticated way than just looking for a matching name.

This dilemma has nothing to do with dispatch entirely by name (which,
incidently, is _not_ "duck typing"): even the example that I gave
allowed for dispatch on the invocant (which includes multiple
inheritance and access to roles), and the problem wouldn't go away if
I put "multi" in front of the keywords, bringing MMD into play.

(I know a guy who works in building maintenance and also does moonlighting
as a computer tech.  In either of his two roles, he could be said to "do
windows".  But what windows he does when someone asks him to do windows is
disambiguated by his current role.)

Thanks for the example; this will make things more concrete.

   role Janitor {
     method do_windows() { #<code> }
     method sweep_floors() { #<code> }
   }
   sub clean_up ( Janitor $joe ) { $joe.do_windows(); $joe.sweep_floors(); }

   role Tech {
     method do_windows() { #<code> }
     method do_linux() ( #<code> }
   }
   sub program ( Tech $tom, Bool $boss_is_idiot ) {
     if $boss_is_idiot { $tom.do_windows() } else { $tom.do_linux() }
   }

   class Moonlighter does Tech does Janitor {
     method do_windows() { #<????> }
   }

   my Moonlighter $sam;
   clean_up($sam); # calls Moonlighter::do_windows()
   program($sam, :boss_is_idiot); # calls Moonlighter::do_windows()

--
Jonathan "Dataweaver" Lang

Reply via email to