module Methods {
// INSTANCE METHODS
// instance methods can be added for a type and then called using a "dot"
// syntax e.g. x.f() instead of f(x).
// the module defining the method must be imported.
import { /Std/Math; }
struct Vector {
x : double;
y : double;
z : double;
}
// the following defines a method for the double type (first parameter)
// as a convention the first parameter is shown as this, but can be any name
lerp(this : double, to : double, weight : double) : double => {
// calculate linear interpolation between this and to given fraction weight
return this * (1.0 - f) + (to * weight);
}
fn test1() {
let x = 1.0;
// the logical equivalent of calling lerp(x, 2.0, 0.5)
let y = x.lerp(2.0, 0.5);
}
// METHOD NAME UNIQUENESS
// method names only need to be unique for the type they apply to
// method names must not conflict with field names of the type they apply to
// the following defines a lerp method for the Vector type (first parameter)
lerp(this : Vector, to : Vector, weight : double) : double => {
// apply linear interpolation to a vector
return Vector3(
this.x.lerp(to.x, weight),
this.y.lerp(to.y, weight),
this.z.lerp(to.z, weight)
);
}
fn test2() {
let v1 = Vector(1, 2, 3);
let v2 = Vector(4, 5, 6);
let v3 = v1.lerp(v2);
}
// PROPERTIES
// property getters and setters are defined using .get or .set
// note: the variable this could be named anything
magnitude.get(this : Vector) : double => {
return sqrt(
this.x * this.x +
this.y * this.y +
this.z * this.z
)
}
fn test4() {
let v = Vector(1, 2, 3);
let m = v.magnitude;
}
// INDEXERS
// indexers can be defined using get[] or set[]
// actual index can be any type (not limited to numbers)
get[](this : Vector, index : string) : double => {
// return the X, Y, or Z index
return match (index) {
"x" => this.x;
"y" => this.y;
"z" => this.z;
_ => NaN // handle invalid argument
}
}
fn test5() {
let v = Vector3(1, 2, 3);
let z = v["z"];
}
// MULTIPLE INDICES
// A get[]/set[] can have multiple parameters for the indices
struct Table {
width: int;
cells : int[];
}
get[](this : Table, row : int, col : int) : int => {
let index = row * width + col;
return this.cells[index];
}
fn test6() {
let table = Table(3,[0, 1, 2, 3, 4, 5]);
let cell = table.get[1, 0]; // 3
}
// STATIC METHODS
// static methods are defined for a type by listing the name of the type
// followed by the method name.
Vector.sum(...vectors: Vector[]) : Vector => {
let x = 0.0, y = 0.0, z = 0.0;
for (v in vectors) {
x += v.x;
y += v.y;
z += v.z;
}
return Vector(x, y, z);
}
fn test7() {
let v1 = Vector(1, 2, 3);
let v3 = Vector(3, 4, 5);
// use the type name followed by the method name to invoke a static method
let v3 = Vector.sum(v1, v2);
}
}