Vector

class Vector {
    has Real $.x;
    has Real $.y;

    multi submethod BUILD (:$!x!, :$!y!) {
        *
    }
    multi submethod BUILD (:$length!, :$angle!) {
        $!x = $length * cos $angle;
        $!y = $length * sin $angle;
    }
    multi submethod BUILD (:from([$x1, $y1])!, :to([$x2, $y2])!) {
        $!x = $x2 - $x1;
        $!y = $y2 - $y1;
    }

    method length { sqrt $.x ** 2 + $.y ** 2 }
    method angle  { atan2 $.y, $.x }

    method add      ($v) { Vector.new(x => $.x + $v.x,  y => $.y + $v.y) }
    method subtract ($v) { Vector.new(x => $.x - $v.x,  y => $.y - $v.y) }
    method multiply ($n) { Vector.new(x => $.x * $n,    y => $.y * $n  ) }
    method divide   ($n) { Vector.new(x => $.x / $n,    y => $.y / $n  ) }

    method gist { "vec[$.x, $.y]" }
}

multi infix:<+>  (Vector $v, Vector $w) is export { $v.add: $w }
multi infix:<->  (Vector $v, Vector $w) is export { $v.subtract: $w }
multi prefix:<-> (Vector $v)            is export { $v.multiply: -1 }
multi infix:<*>  (Vector $v, $n)        is export { $v.multiply: $n }
multi infix:</>  (Vector $v, $n)        is export { $v.divide: $n }


#####[ Usage example: ]#####

say my $u = Vector.new(x => 3, y => 4);                #: vec[3, 4]
say my $v = Vector.new(from => [1, 0], to => [2, 3]);  #: vec[1, 3]
say my $w = Vector.new(length => 1, angle => pi/4);    #: vec[0.707106781186548, 0.707106781186547]

say $u.length;                                         #: 5
say $u.angle * 180/pi;                                 #: 53.130102354156

say $u + $v;                                           #: vec[4, 7]
say $u - $v;                                           #: vec[2, 1]
say -$u;                                               #: vec[-3, -4]
say $u * 10;                                           #: vec[30, 40]
say $u / 2;                                            #: vec[1.5, 2]