Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: 72d4c05e8c
Fetching contributors…

Cannot retrieve contributors at this time

file 170 lines (145 sloc) 5.937 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
use v6;

use Test;

plan 40;

# L<S06/Routine modifiers/>
# L<S06/Parameters and arguments/>

# multi sub with signature
multi sub foo() { "empty" }
multi sub foo($a) { "one" } #OK not used
is(foo(), "empty", "multi sub with empty signature");
is(foo(42), "one", "multi sub with parameter list");

# multi sub without signature
multi sub bar { "empty" }
multi sub bar($a) { "one" } #OK not used
#?niecza skip 'No candidates for dispatch to &bar'
is(bar(), "empty", "multi sub with no signature");
#?niecza skip 'Ambiguous dispatch for &bar'
#?pugs todo
is(bar(42), "one", "multi sub with parameter list");

# multi without a routine type
multi baz { "empty" }
multi baz($a) { "one" } #OK not used
#?niecza skip 'No candidates for dispatch to &baz'
is(baz(), "empty", "multi with no signature");
#?niecza skip 'Ambiguous dispatch for &baz'
#?pugs todo
is(baz(42), "one", "multi with parameter list");

# multi without a routine type with signature
multi foobar() { "empty" }
multi foobar($a) { "one" } #OK not used
is(foobar(), "empty", "multi with empty signature");
is(foobar(42), "one", "multi with parameter list");

# multi with some parameters not counting in dispatch (;;) - note that if the
# second parameter is counted as part of the dispatch, then invoking with 2
# ints means they are tied candidates as one isn't narrower than the other.
# (Note Int is narrower than Num - any two types where one is narrower than
# the other will do it, though.)
class T { }
class S is T { }
multi foo(S $a, T $b) { 1 } #OK not used
multi foo(T $a, S $b) { 2 } #OK not used
multi bar(S $a;; T $b) { 1 } #OK not used
multi bar(T $a;; S $b) { 2 } #OK not used
my $lived = 0;
try { foo(S,S); $lived = 1 }
#?pugs todo
is($lived, 0, "dispatch tied as expected");
#?niecza skip 'Ambiguous dispatch for &bar'
#?pugs skip 'missing invocant'
is(bar(S,S), 1, "not tied as only first type in the dispatch");

# not allowed to declare anonymous routines with only, multi or proto.
#?niecza todo
eval_dies_ok 'only sub {}', 'anonymous only sub is an error';
eval_dies_ok 'multi sub {}', 'anonymous multi sub is an error';
eval_dies_ok 'proto sub {}', 'anonymous proto sub is an error';
#?niecza todo
eval_dies_ok 'only {}', 'anonymous only is an error';
eval_dies_ok 'multi {}', 'anonymous multi is an error';
eval_dies_ok 'proto {}', 'anonymous proto is an error';
#?niecza todo
eval_dies_ok 'class A { only method {} }', 'anonymous only method is an error';
eval_dies_ok 'class B { multi method {} }', 'anonymous multi method is an error';
eval_dies_ok 'class C { proto method {} }', 'anonymous proto method is an error';

#?rakudo skip 'Multi typename...maybe deprecated?'
#?niecza skip 'Undeclared name Multi'
#?pugs skip 'Undeclared name Multi'
ok(&foo ~~ Multi, 'a multi does Multi');
#?pugs skip 'Callable'
ok(&foo ~~ Callable, 'a multi does Callable');
#?niecza todo
#?pugs skip 'parsefail'
ok(~&foo ~~ /foo/, 'a multi stringifies sensibly');

# note - example in ticket [perl #58948] a bit more elaborate
{
    multi sub max($a, $b, $c) {return 9} #OK not used

    lives_ok { max(1, 2, 3) }, 'use multi method to override builtin lives';
    #?pugs todo
    is eval('max(1, 2, 3)'), 9, 'use multi method to override builtin';
}

# named and slurpy interaction - there have been bugs in the past on this front
{
    multi nsi_1(Int $x, Bool :$flag, *@vals) { "nsi 1" }; #OK not used
    is nsi_1(1), 'nsi 1', 'interaction between named and slurpy (1)';
    is nsi_1(1, 2, 3, 4, 5), 'nsi 1', 'interaction between named and slurpy (2)';

    multi nsi_2(Bool :$baz = Bool::False, *@vals) { "nsi 2" }; #OK not used
    is nsi_2(:baz(Bool::True), 1, 2, 3), 'nsi 2', 'interaction between named and slurpy (3)';
    is nsi_2(1, 2, 3), 'nsi 2', 'interaction between named and slurpy (4)';
}

# RT #68234
{
    multi rt68234(:$key!) { 'with key' }; #OK not used
    multi rt68234(*%_) { 'unknown' }; #OK not used
    #?pugs todo
    is rt68234(:key), 'with key', 'can find multi method with key';
    #?pugs skip 'Named argument found where no matched parameter expected'
    is rt68234(:unknown), 'unknown', 'can find multi method with slurpy';
}

# RT #68158
#?pugs skip 'todo flipflops the first test response'
{
    multi rt68158() { 1 }
    multi rt68158(*@x) { 2 } #OK not used
    is rt68158(), 1, 'non-slurpy wins over slurpy';
    is rt68158(9), 2, 'slurpy called when non-slurpy can not bind';
}

# RT #64922
#?pugs todo
{
    multi rt64922($x, %h?) { 1 } #OK not used
    multi rt64922(@x) { 2 } #OK not used
    is rt64922(1), 1, 'optional parameter does not break type-based candidate sorting';
    is rt64922([1,2]), 2, 'optional parameter does not break type-based candidate sorting';
}

# RT #65672
{
    multi rt65672() { 99 }
    multi rt65672($x) { $x }
    sub rt65672caller( &x ) { &x() }
    is rt65672caller( &rt65672 ), 99, 'multi can be passed as callable';
}

# We had a bug where the multiness leaked into a sub, so we got errors
# about anonymous methods not being allowed to be multi.
#?pugs skip 'parsefail'
{
    multi sub kangaroo() { return method () { self * 2 } }
    my $m = kangaroo();
    is 21.$m(), 42, 'can write anonymous methods inside multi subs';
}


# RT #75136
# a multi declaration should only return the current candidate, not the whole
# set of candidates.
#?pugs skip 'parsefail'
{
    multi sub koala(Int $x) { 42 * $x };

    my $x = multi sub koala(Str $x) { 42 ~ $x }
    is $x.candidates.elems,
        1, 'multi sub declaration returns just the current candidate';
    is $x('moep'), '42moep', 'and that candidate works';
    dies_ok { $x(23) }, '... and does not contain the full multiness';
}

multi with_cap($a) { $a }
multi with_cap($a,$b,|cap) { return with_cap($a + $b, |cap) }
#?pugs skip 'with_cap not found'
is with_cap(1,2,3,4,5,6), 21, 'captures in multi sigs work';

done;

# vim: ft=perl6
Something went wrong with that request. Please try again.