p5h / p5summit-2019

Perl 5 Summit
0 stars 0 forks source link

Multi method dispatch #7

Open toddr opened 4 years ago

toddr commented 4 years ago

Same name different signatures.

leonerd commented 4 years ago

This is a huge and slippery minefield. Right now signatures basically only match on the quantity of arguments passed and are not sensitive to the values contained therein. Thus you could

multi sub add($x) { ... }
multi sub add($x, $y) { ... }

currently and it would have some hopefully-expected dispatch semantics. However, if that's as far as it goes then it's hard to imagine in practice what different behaviours the different-arity implementations of this function would have that can't be accounted for by just providing default values for the missing arguments:

sub add($x, $y = 1) { ... }

and in fact even more generally you can always detect the case because of the way the expressions are written:

sub add($x, $y = (my $y_was_missing = 1), 1) { ... }
leonerd commented 4 years ago

The slippery minefield (am I mixing my metaphors?) comes if we want to consider dispatch by considering anything about the runtime values contained within those parameters. E.g. a common point that some other languages might jump into first off the bat is to consider a multiple-dispatch method which distinguishes strings from numbers:

multi sub bark($x : str) { ... }
multi sub bark($x : num) { ... }

which I feel would be a huge departure from anything we have existing in Perl. If you added that then the temptation would be now to ask why don't we have such type annotations on non-multiple dispatch?

sub roar ($x : str) { ... }

At which point why can I only put such type-restricting declarations on sub parameters and not regular variables?

my $y : str = func();

Or can I now use these types to dispatch other things in Perl? Maybe a typed switch-like statement?

cond($z) {
   where(str) { say "z is a string" }
}

Maybe I get typed catch (a commonly-requested feature)... Maybe we can do regexp matches and allsorts and this begins to feel like smartmatch all over again and I think I want to stop here.

tonycoz commented 4 years ago

When I saw this I thought it referred to dispatching on the dynamic type of more than one object.

ie.

# definitions elided
package B {} package C1 { our @ISA = 'B'; } package C2 { out @ISA = 'B';}
package Foo {
   sub f ($self, $b : C1) { ... }  # One
   sub f ($self, my $b : C2) { ... } # Two
}
package Bar {
   sub f ($self, my $b : C1) { ... } # Three
   sub f ($self, my $b : B) { ... } # Four
}
my $o1 = Foo->new;
my $o2 = C2->new;
my $o3 = Bar->new;
$o1->f($o2);  # calls Two
$o3->f($o2); # calls Four

https://en.wikipedia.org/wiki/Multiple_dispatch

atoomic commented 4 years ago

I think what @toddr described is function polymorphism

xsawyerx commented 4 years ago

I dislike multi-method dispatching with a passion, to be honest.

Leont commented 4 years ago

Multi method dispatch requires a kind of type system that we don't have. I suspect this will fail for exactly the same kinds of reasons why smartmatch failed.