Skip to content
Sword

Generics

func Max[T](a T, b T) T {
if a > b {
return a
}
return b
}
func main() int {
x := Max(20, 22)
y := Max[i32](1, 2)
return int(x) + int(y) - 2
}

Each combination of types becomes a real compiled copy. There is no boxing and no indirection. Type arguments are usually inferred from what you pass; write them out when they cannot be.

Constraints are the same interfaces from the last section:

interface Sized {
Size() u64
}
struct Box {
w u64
h u64
}
func (b *Box) Size() u64 {
return b.w * b.h
}
func total[T: Sized](a *T, b *T) u64 {
return a.Size() + b.Size()
}
func main() int {
mut p := Box{w: 3, h: 4}
mut q := Box{w: 5, h: 6}
return int(total(&p, &q))
}

One concept, two kinds of polymorphism. The difference is where the call is resolved: through a constraint it is decided at instantiation and compiles to a direct call, while an interface parameter goes through the method table at run time.

Two builtins exist because a generic allocator cannot work them out for itself: sizeof[T]() and alignof[T](), both compile-time constants.