Vector

class MyVector(:args) {

    has Number x
    has Number y

    method init {
        if ([:x, :y] ~~ args) {
            x = args{:x}
            y = args{:y}
        }
        elsif ([:length, :angle] ~~ args) {
            x = args{:length}*args{:angle}.cos
            y = args{:length}*args{:angle}.sin
        }
        elsif ([:from, :to] ~~ args) {
            x = args{:to}[0]-args{:from}[0]
            y = args{:to}[1]-args{:from}[1]
        }
        else {
            die "Invalid arguments: #{args}"
        }
    }

    method length { hypot(x, y) }
    method angle  { atan2(y, x) }

    method +(MyVector v) { MyVector(x => x + v.x,  y => y + v.y) }
    method -(MyVector v) { MyVector(x => x - v.x,  y => y - v.y) }
    method *(Number n)   { MyVector(x => x * n,    y => y * n)   }
    method /(Number n)   { MyVector(x => x / n,    y => y / n)   }

    method neg  { self * -1 }
    method to_s { "vec[#{x}, #{y}]" }
}

var u = MyVector(x => 3, y => 4)
var v = MyVector(from => [1, 0], to => [2, 3])
var w = MyVector(length => 1, angle => 45.deg2rad)

say u    #: vec[3, 4]
say v    #: vec[1, 3]
say w    #: vec[0.70710678118654752440084436210485, 0.70710678118654752440084436210485]

say u.length                             #: 5
say u.angle.rad2deg                      #: 53.13010235415597870314438744090659

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]