In a message dated Wed, 27 Sep 2006, Aaron Sherman writes:
Any thoughts?
I'm still thinking about the practical implications of this... but what
immediately occurs to me:
The point of multiple, as opposed to single, dispatch (well, one of the
points, and the only point that matters when we're talking about multis of
a single invocant) is that arguments are not bound to a single type. So at
first gloss, having a single prototype in the core for all same-named
multis as in your proposal seems to defeat that use, because it does
constrain arguments to a single type.
I would hate for Perl 6 to start using C<Any> or C<Whatever> in the sort
of ways that many languages abuse "Object" to get around the restrictions
of their type systems. I think that, as a rule, any prototype
encompassing all variants of a multi should not only specify types big
enough to include all possible arguments, but also specify types small
enough to exclude impossible arguments.
In other words, to use your proposal, "our proto moose (Moose $x:)" should
assert not just that all calls to the multi moose will have an invocant
that does Moose, but also that all objects of type Moose will work with a
call to the multi moose. That may have been implicit in your proposal,
but I wanted to make it explicit.
In practice, the ability to use junctive types, subsets, and roles like
any other type makes the concept of "single type" a much less restrictive
one in Perl 6 than in most languages. For example, if you wanted C<max>
to work on both arrays and hashes, you could have
our proto max (Array|Hash $container)
Or you could define an C<Indexed> role that both Array and Hash do and
have:
our proto max (Indexed $container)
So maybe this is a reasonable constraint. But it seems odd to me that
Perl might then not allow me to write a C<max> that takes, say, Bags or
Herds or whatever. And as I said before, I think a prototype of
our proto max (Whatever $container)
is incorrect too. What I really want is for max to be callable on
anything that can do max, and not on anything that can't. Following that
observation to its logical conclusion, at some point we get to the core
containing prototypes like:
our proto max(Maxable $container)
our proto sort(Sortable $container)
our proto keys(Keyable $container)
which (I think) results in no better support for contracts, but merely
requires gratuitious typing (in both senses of the word): where before we
could just write our routine "multi max...", now we need to write both
"multi max..." and remember to add "does Maxable" so Perl will let us
compile it.
My apologies if I'm attacking a strawman here; perhaps there's a saner way
to allow the flexibility for users to define novel implementations of
global multis while still having the prototypes well-typed.
All that said, the globalness of multis does concern me because of the
possibility of name collision, especially in big systems involving multis
from many sources. Your proposal would at least make an attempt to define
a multi not type-conformant with a core prototype throw a compile-time
error, rather than mysterious behavior at runtime when an unexpected multi
gets dispatched.
Trey