Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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

  • trait and impl ... for ....
  • Generic functions and impls with bounds such as T: Ord.