Traits and generics
trait Describe
fn describe(&self) -> text
struct Point
x: i64
y: i64
impl Describe for Point
fn describe(&self) -> text = "(" + self.x.tostr() + ", " + self.y.tostr() + ")"
impl forall[T: Describe] Describe for List[T]
fn describe(&self) -> text = ", ".join([x.describe() for x in self])
fn largest[T: Ord](xs: &[T]) -> T?
var best: T? = none
for x in xs
match best
none -> best = some(copy(x))
some(b) if x > b -> best = some(copy(x))
_ -> pass
return best
const PTS: List[Point] = [Point(x: 1, y: 2), Point(x: 3, y: 4)]
const NUMS: List[i64] = [4, 9, 2]
check Point(x: 1, y: 2).describe() == "(1, 2)"
check PTS.describe() == "(1, 2), (3, 4)"
check largest(&NUMS) == some(9)
Traits
A trait lists functions that a type promises to have. impl Describe for Point keeps that promise for Point.
impl forall[T: Describe] Describe for List[T] says: for every type T
that implements Describe, a list of T implements it too. The word
forall is needed so the grammar can tell the parameter list apart from a
slice type [T].
Generic functions
largest[T: Ord](xs: &[T]) -> T? works for any type T that can be
ordered. Ord is a bound: the checker refuses a call with a type that
cannot be compared. Inside, copy(x) is needed because best keeps its
own value while xs is only borrowed.
The arm some(b) if x > b -> ... shows a guard on a match arm, the same
idea as a guard on a step.
What you learned
traitandimpl ... for ....- Generic functions and impls with bounds such as
T: Ord.