Implementing Std Traits
Implementing a standard trait lets the language treat your type exactly like a
built-in. Implement core::cmp::Ord — one method, cmp, returning -1 / 0 / 1
— and all four comparison operators (<, >, <=, >=) are derived from it
automatically. Your type also satisfies any T: Ord bound in generic functions:
Money implements core::cmp::Ord via cmp; smaller<T: core::cmp::Ord> accepts it as a generic argument.
18-impl-std-trait.zolo
// Feature: implementing Ord so YOUR type works with comparison + Ord bounds
// Syntax: `impl Ord for MyType { fn cmp(self, other: MyType) -> int { ... } }`
// When to use: you want `<`/`>`/`<=`/`>=` on your struct, and to pass it to a
// generic `fn f<T: Ord>`. Implement `cmp` (returns -1 / 0 / 1) — all four
// comparison operators are derived from it, and the `T: Ord` bound is satisfied.
// (`==`/`!=` already work structurally on every struct, no impl needed.)
struct Money (
cents: int,
) {
impl core::cmp::Ord {
fn cmp(self, other: Money) -> int {
match self.cents - other.cents {
d if d < 0 => -1,
d if d > 0 => 1,
_ => 0,
}
}
}
}
fn smaller<T: core::cmp::Ord>(a: T, b: T) -> T { a > b && b || a }
print(smaller(Money { cents: 500 }, Money { cents: 300 }).cents) // 300
print(Money { cents: 5 } < Money { cents: 9 }) // true
print(Money { cents: 5 } == Money { cents: 5 }) // true (structural)
// expected:
// 300
// true
// true
A few things to note:
==and!=are structural by default — every struct gets them for free without an explicitEqimpl.cmpdrives all four operators — you only write one method and the language derives the rest from it.- Qualified trait path —
impl core::cmp::Ord(the full path) is the same asimpl Ord; using the qualified form makes the origin clear.
Challenge
Add a second struct Weight with a grams: float field and the same
core::cmp::Ord impl. Pass both Money and Weight to smaller and confirm
that the same generic function works for both types.