Operator traits
Operator traits
Operators are not built in to the numeric types. An operator applied to an object calls a method; an operator applied to a raw machine scalar lowers directly to an instruction.
| Operator | Method | Trait |
|---|---|---|
+ |
plus |
Plus<T> |
- |
minus |
Minus<T> |
* |
multiply |
Multiply<T> |
/ |
divide |
Divide<T> |
** |
exp |
Exp<T> |
% |
modulo |
Mod<T> |
== |
equals |
Equals<T> |
!= |
not_equals |
NotEquals<T> |
> |
greater_than |
GreaterThan<T> |
< |
less_than |
LessThan<T> |
>= |
greater_than_equals |
GreaterThanEquals<T> |
<= |
less_than_equals |
LessThanEquals<T> |
&& |
and |
And<T> |
|| |
or |
Or<T> |
! |
not |
Not |
Dispatch is by method name
This is the part that surprises people. The compiler looks for a method with
the right name and signature, not for a declared impl. A class that defines
equals(other: X) => bool supports == whether or not it says
impl Equals<X>.
xml::Element is exactly that case: it defines equals but does not declare the
trait.
The declaration still matters for bounds. A type that only has the method
satisfies the operator but does not satisfy impl Equals, so it cannot be
used where that bound is required, such as a Map key. Declare the trait when
the type is meant to be usable generically.
Short-circuiting
&& and || between two booleans short-circuit on the raw value and never call
And or Or. Enum comparison with == compares the variant directly.
Implementing one
[public] class Money impl Plus<Money>, Equals<Money> {
cents: i64
[public] fn plus(other: Money) => Money {
return new Money(this.cents + other.cents)
}
[public] fn equals(other: Money) => bool {
return this.cents == other.cents
}
}