I think it would helpful if the spec addressed "who wins" in MMD when
optional arguments are present.
I just submitted these failing tests for pugs which illustrate the
issue.
not ok 11 - Arguments (a => 'b') to signatures 1. () and 2. (*%h) calls 2
not ok 14 - Arguments () to signatures 1. (@a?) and 2. () calls 2
not ok 15 - Arguments (<1 2 3>) to signatures 1. () and 2. (@a?) calls 2
In summary, matches that should otherwise happen are failing because
the "optionalness".
Mark
Reference:
http://feather.perl6.nl/syn/S12.html#Multisubs_and_Multimethods
I just patched mmd-draft.txt in the pugs tree to try address optionals.
Here's what I came up with:
== Handling Optional and Slurpy Parameters
Optional parameters need special consideration, because they represent
two options themselves: one with with the argument and one without.
Slurpy parameters have the same concern, as they can take zero or more
arguments themselves. For each optional parameter, a case with and
without the optional parameter is considered.
Examples:
Arguments (a => 'b') to signatures 1. () and 2. (*%h) calls 2
Arguments () to signatures 1. (@a?) and 2. () calls 2
Arguments (<1 2 3>) to signatures 1. () and 2. (@a?) calls 2
Mark
I took a break and thought of an important further clarification for
this. The updated text is below:
== Handling Optional and Slurpy Parameters
Optional parameters need special consideration, because they represent
two options themselves: one with with the argument and one without.
Slurpy parameters have the same concern, as they can take zero or more
arguments themselves. For each optional parameter, a case with and
without the optional parameter is considered.
Examples:
Arguments (a => 'b') to signatures 1. () and 2. (*%h) calls 2
Arguments (<1 2>) to signatures 1. (@a?) and 2. (@a) calls 2
Arguments (<1 2 3>) to signatures 1. () and 2. (@a?) calls 2
Arguments (@a) to signatures 1. (@a?) and 2. (@a) IS TIE
Note that the variant /with/ the parameter can be considered an exact
match, but but the variant /without/ it cannot be considered an exact
match. That rule makes the following example work:
On 9/3/06, Mark Stosberg <ma...@summersault.com> wrote:
> Examples:
> Arguments (<1 2>) to signatures 1. (@a?) and 2. (@a) calls 2
For example, I would expect this one to be ambiguous, because the 1.
(@a?) sub introduces two different signatures, 1. () and 1. (@a).
When given <1 2>, 1. (@a) matches as well as 2. (@a), so it is
ambiguous.
> Arguments (@a) to signatures 1. (@a?) and 2. (@a) IS TIE
The only difference I can see between this and the one above is @a vs.
<1 2>, which ought to behave the same way, right?
> Note that the variant /with/ the parameter can be considered an exact
> match, but but the variant /without/ it cannot be considered an exact
> match.
And I expect that if either or both matches the method is considered
to be a match. Right?
Luke
Oops. Yes, I would call that a tie, too.
>> Arguments (@a) to signatures 1. (@a?) and 2. (@a) IS TIE
>
> The only difference I can see between this and the one above is @a vs.
> <1 2>, which ought to behave the same way, right?
Yes.
>> Note that the variant /with/ the parameter can be considered an exact
>> match, but but the variant /without/ it cannot be considered an exact
>> match.
>
> And I expect that if either or both matches the method is considered
> to be a match. Right?
Let's look again at the last example:
Arguments () to signatures 1. (@a?) and 2. () calls 2
(@a?) really means () OR (@a). The "()" implicit in (@a?) is a match,
but not an exact match, so the "()" declared by itself wins, because it
/is/ an exact match.
Mark
I don't know about a possible syntax, but sometimes it's a very nice way to
dispatch to different parts.
(I know that that's possible with if statements, but they have a disadvantage:
they're not so visually "dispatching", if you know what I mean).
Regards,
Phil
Why, yes, see the various Unpacking sections in S06, as well as "where"
type constraints. We're st^H^Hadapting as much as we can. :-)
Audrey
I now had a look at http://dev.perl.org/perl6/doc/design/syn/S06.html but
didn't find what I meant.
Sorry if I'm just dumb and don't understand you (or S06); I'll try to explain
what I mean.
In Haskell you can eg. write:
SomeThing :: Int -> Int -> Int
SomeThing a b
| a = 4 : b+2
| b = 3 : a+1
| otherwise : a*b
or
AnotherThing :: Int -> Int -> Int
AnotherThing 4 b = b+2
AnotherThing b 3 = a+1
AnotherThing a b = a*b
In Perl5 this looks like
sub SomeThing
{
my($a, $b)=@_;
return b+2 if ($a == 4);
return a+1 if ($b == 3);
return a*b;
}
Which is a bit wrong IMO, because the condition should be first.
But
sub SomeThing
{
my($a, $b)=@_;
if ($a == 4) { return b+2 }
if ($b == 3) { return a+1 }
return a*b;
}
is a bit of a hazzle with the {} and repeated if()s.
What I am asking is whether there will be some multimethod dispatch depending
on the *value*, not the *type*, of parameters.
Perl6 could possibly do something with "given"; but matching on multiple
variables seems to be verbose, too.
I'm looking for something in the way of
sub SomeThing(Num $a, Num $b) where $a==4 is $b+2;
sub SomeThing(Num $a, Num $b) where $b==3 is $a+1;
sub SomeThing(Num $a, Num $b) { return $a * $b }
but without specifying the signature multiple times (or maybe we should, since
it's MMD). Now
sub SomeThing(Num $a, Num $b)
{
if $a==4 { return $b+2; }
if $b==3 { return $a+1; }
return $a * $b;
}
would almost do what I want, but I don't know if the compiler would optimize
that in the way it could for direct MMD depending on types.
Regards,
Phil
I don't think you're dumb; the Synopses just require that you intuit
certain things from each other, from examples in other Synopses, and so on
in a Perlish sort of way; what you're looking for is not spelled out
explicitly. It can be found by noticing how you specify subtypes, along
with noticing that subtypes can be specified as parameter types. There's
also an example showing explicitly what you want in S12.
> In Perl5 this looks like
>
> sub SomeThing
> {
> my($a, $b)=@_;
>
> return b+2 if ($a == 4);
> return a+1 if ($b == 3);
> return a*b;
> }
> [...]
> What I am asking is whether there will be some multimethod dispatch depending
> on the *value*, not the *type*, of parameters.
> Perl6 could possibly do something with "given"; but matching on multiple
> variables seems to be verbose, too.
> I'm looking for something in the way of
>
> sub SomeThing(Num $a, Num $b) where $a==4 is $b+2;
> sub SomeThing(Num $a, Num $b) where $b==3 is $a+1;
> sub SomeThing(Num $a, Num $b) { return $a * $b }
It's just
multi sub SomeThing(Num $a where {$^a == 4}, Num $b) { $b + 2 }
multi sub SomeThing(Num $a, Num $b where {$^b == 3}) { $a + 1 }
multi sub SomeThing(Num $a, Num $b) { $a * $b }
> but without specifying the signature multiple times (or maybe we should, since
> it's MMD). Now
Yes, the signatures are different--the first two multis specify subtypes
as their signatures, the last specifies a canonical type.
Trey
> It's just
>
> multi sub SomeThing(Num $a where {$^a == 4}, Num $b) { $b + 2 }
> multi sub SomeThing(Num $a, Num $b where {$^b == 3}) { $a + 1 }
> multi sub SomeThing(Num $a, Num $b) { $a * $b }
>
> Yes, the signatures are different--the first two multis specify subtypes
> as their signatures, the last specifies a canonical type.
Thank you *very* much! That clears it up.
Regards,
Phil
> [Haskell]
> SomeThing a b
> | a = 4 : b+2
> | b = 3 : a+1
> | otherwise : a*b
>
> In Perl5 this looks like
>
> sub SomeThing
> {
> my($a, $b)=@_;
>
> return b+2 if ($a == 4);
> return a+1 if ($b == 3);
> return a*b;
> }
Or like:
sub SomeThing
{
alias my ($p, $q) = @_ ;
$p == 4 ? $q + 2 :
$q == 3 ? $p + 1 :
$p * $q ;
}
--
Groet, Ruud
Every scalar value is a one-element subset of its type, so you can just write:
multi sub SomeThing(Num 4, Num $b) { $b + 2 }
multi sub SomeThing(Num $a, Num 3) { $a + 1 }
multi sub SomeThing(Num $a, Num $b) { $a * $b }
or even just
multi sub SomeThing(4, Num $b) { $b + 2 }
multi sub SomeThing(Num $a, 3) { $a + 1 }
multi sub SomeThing(Num $a, Num $b) { $a * $b }
Though 3 and 4 are arguably going to match against Int rather than Num...
Larry