Generics
Generics let one declaration work with several types. Zap specializes generic code at compile time.
Generic functions
Section titled “Generic functions”Declare type parameters after the function name:
fun identity<T>(value: T) T { return value;}
fun main() Int { var number = identity(42); var text = identity("Zap"); return number;}The compiler normally infers T from the arguments. You can also write an
explicit type argument:
var number = identity<Int>(42);Use commas for multiple type parameters:
record Pair<A, B> { first: A, second: B,}
var entry = Pair<String, Int> { first: "apples", second: 3 };Generic classes
Section titled “Generic classes”class Box<T> { priv value: T;
fun init(value: T) { self.value = value; }
pub fun get() T { return self.value; }}
fun main() Int { var box = new Box<String>("hello"); println(box.get()); return 0;}Constraints
Section titled “Constraints”A where clause requires a type argument to inherit from a given class:
class Animal { pub fun sound() Int { return 0; }}
class Dog : Animal { pub fun sound() Int { return 1; }}
fun speak<T>(value: T) Int where T: Animal { return value.sound();}The compiler rejects speak(value) when the type of value does not satisfy
the constraint.
Compile-time type branches
Section titled “Compile-time type branches”Use iftype inside generic code when an implementation depends on the concrete
type:
fun kind<T>(value: T) String { iftype T == Int { return "integer"; } else iftype T == Bool { return "boolean"; } else { return "other"; }}Only the selected branch is compiled for a specialization. Prefer ordinary generic code when every type can share the same implementation.