Defining Your Own Operators

Operators are just subs with special names (infix, prefix, postfix, circumfix, postcircumfix) and are lexically scoped: they're only active where they're defined or imported.

sub postfix:<!>(Int $n where * >= 0) { [*] 1..$n }
say 5!;                                 # 120

sub infix:<±>($a, $b) { ($a - $b, $a + $b) }
say 10 ± 2;                             # (8 12)

sub prefix:<√>($x) { $x.sqrt }
say √16;                                # 4

sub circumfix:<⌊ ⌋>($x) { $x.floor }
say ⌊3.7⌋;                              # 3

sub postcircumfix:<⟨ ⟩>(@list, $i) { @list[$i] }
my @l = <a b c>;
say @l⟨1⟩;                              # b

sub infix:<avg>($a, $b) is equiv(&infix:<+>) { ($a + $b) / 2 }   # precedence trait
say 4 avg 8;                            # 6

sub infix:<**!>($a, $b) is assoc<right> is tighter(&infix:<*>) { $a ** $b }

# Overload an existing operator for your type
class Vec { has $.x; has $.y; method gist { "Vec($!x, $!y)" } }
multi sub infix:<+>(Vec $a, Vec $b) { Vec.new(x => $a.x + $b.x, y => $a.y + $b.y) }
multi sub infix:<*>(Vec $a, Numeric $k) { Vec.new(x => $a.x * $k, y => $a.y * $k) }
multi sub infix:<==>(Vec $a, Vec $b) { $a.x == $b.x && $a.y == $b.y }
say Vec.new(:1x, :2y) + Vec.new(:3x, :4y);   # Vec(4, 6)
say Vec.new(:1x, :2y) * 3;                   # Vec(3, 6)
# Meta-operators work on new operators automatically:
say [+] Vec.new(
…