Multiple Dispatch
Candidates are ordered by narrowness: more specific types and constraints win. Ties raise an "Ambiguous call" error. where clauses are checked in declaration order among equally narrow candidates.
# Dispatch by type
multi sub describe(Int $x) { "Int: $x" }
multi sub describe(Str $x) { "Str: '$x'" }
multi sub describe(Rat $x) { "Rat: $x" }
multi sub describe(@x) { "Positional with {@x.elems} elements" }
multi sub describe(%x) { "Associative with keys {%x.keys.sort}" }
multi sub describe($x) { "Something else: {$x.^name}" }
say describe($_) for 42, 'hi', 1.5, [1, 2], {a => 1}, 3e0;
# Dispatch by value and constraint
multi fib(0) { 0 }
multi fib(1) { 1 }
multi fib(Int $n where * > 1) { fib($n - 1) + fib($n - 2) }
say fib(20); # 6765
multi factorial(0) { 1 }
multi factorial(Int $n where * > 0) { $n * factorial($n - 1) }
# Dispatch by arity and named arguments
multi area(Numeric $side) { $side ** 2 }
multi area(Numeric $w, Numeric $h) { $w * $h }
multi area(:$radius!) { π * $radius ** 2 }
say area(3), ' ', area(2, 5), ' ', area(radius => 1);
# proto: define the shared interface and wrap the candidates
proto sub process(|) {
say "before";
{*} # dispatch to the best candidate
}
multi process(Int $x) { say "int $x" }
multi process(Str $x) { say "str $x" }
process(5);
…