module Generics {
// GENERIC BASICS
// Generic types, functions, and methods allow types to be specified as parameters.
// The following defines a vector type where the types of the components of the
// vector are supplied by the user of the type.
struct Vector{T} {
x : T;
y : T;
z : T;
}
fn test1() {
let v1 = Vector{float}(1.0, 2.0, 3.0); // Vector that uses float for it's components
let v2 = Vector{double}(1.0, 2.0, 3.0); // Vector that uses double for it's components
// if the generic is omitted, the compiler will attempt to infer the types based on context.
let v3 = Vector(1, 2, 3); // Vector{int}(1, 2, 3)
let v4 = Vector(1.0, 2.0, 3.0); // Vector{double}(1, 2, 3)
}
// The following method adds two generic Vectors
add{T}(this : Vector{T}, other: Vector{T}) : Vector{T} => {
return Vector{T}(
this.x + other.x,
this.y + other.y,
this.z + other.z
)
}
fn test2() {
let v1 = Vector(1.0, 1.0, 1.0);
let v2 = Vector(2.0, 2.0, 2.0);
// invoke the add method with two vectors, producing a third
let v3 = v1.add(v2); // Vector{double}(3.0, 3.0, 3.0)
}
// INCOMPATIBLE GENERIC TYPES
// If a generic function is used with a type that is not compatible with it's
// implementation, then the compiler will error
fn test3() {
let v1 = Vector("a", "b", "c");
let v2 = Vector("d", "e", "f");
// compiler error: add method is not compatible with type Vector{string}
let v3 = v1.add(v2);
}
// GENERIC PARAMETER CONSTRAINTS
// To specify constraints on which types can be used, a boolean expression can be
// specified after the generic parameters. this will cause the errors to be
// discovered earlier (when the type is constructed).
// The boolean expression is a constant expression that includes
// the use of ::? (can cast to)
// define a union type for possible vector coordinate types
typedef Coord = float | double | int;
// the boolean expression after => checks if type T can cast to Coord
struct CoordBasedVector{T => T::?Coord} {
x : T;
y : T;
z : T;
}
fn test4() {
let v1 = CoordBasedVector{string}("a", "b", "c"); // error: type constraint failed
}
}