std/core/operators
std/core/src/operators.trb
Add, Subtract, Multiply, Divide, Remainder, Power and Negate, the traits the arithmetic operators go
through, plus OrElse for ?? and Indexed/MutableIndexed/Slice/MutableSlice for a[i] and a[from..to].
Each type parameter list has defaults, which is why with Add alone means Add<Self, Self>.
trait Add
trait Add<Other = Self, Output = Self>
a + b
Examples
print(1 + 2)
fn add
fn add(other: Other): Output
The sum of the two values. This is +.
trait Subtract
trait Subtract<Other = Self, Output = Self>
a - b
fn subtract
fn subtract(other: Other): Output
The difference of the two values. This is -.
trait Multiply
trait Multiply<Other = Self, Output = Self>
a * b
fn multiply
fn multiply(other: Other): Output
The product of the two values. This is *.
trait Divide
trait Divide<Other = Self, Output = Self>
a / b
On the integer types the division truncates toward zero (-7 / 2 is -3), a division by zero panics, and so does
the smallest value of a signed type divided by -1 - an overflow like any other.
fn divide
fn divide(other: Other): Output
The quotient of the two values. This is /.
trait Remainder
trait Remainder<Other = Self, Output = Self>
a % b
On the integer types the remainder takes the sign of the dividend (-7 % 2 is -1), so a is always
(a / b) * b + a % b. A remainder by zero panics.
fn remainder
fn remainder(other: Other): Output
What is left of self after dividing out as many other as fit. This is %.
trait Power
trait Power<Exponent = Self, Output = Self>
a ** b: a raised to the power of b.
** binds tighter than *, / and % and groups to the right, so 2 ** 3 ** 2 is 2 ** 9. A unary - directly
in front of the base is an error, because -x ** 2 reads as -(x ** 2) to a mathematician and as (-x) ** 2 to
a parser: write the one that is meant. The exponent may start with one - x ** -2 means only one thing.
The exponent is a parameter of its own and not Other, because a power is rarely taken by a value of the same kind:
every integer type is raised by an Int (Int8 ** Int), and a float by a float or by an Int.
On the integer types the power is exact, it panics on overflow exactly as * does, and a negative exponent panics
too, because its result is not a whole number. On a float it is IEEE-754 and never panics.
Examples
print(2 ** 10)
print(2.0 ** 0.5)
print(10.0 ** -3)
fn power
fn power(exponent: Exponent): Output
self raised to the power of exponent. This is **.
trait Negate
trait Negate
-a
fn negate
fn negate(): Self
The value with its sign flipped. This is unary -.
trait OrElse
trait OrElse<Value>
a ?? b: the value, or the fallback where there is none.
An operator is a trait exactly when it is a method call, and a ?? b is a.orElse(b) - so this is the trait it
goes through, like Add for +. Option and Result come with it. The fallback is lazy, so it is evaluated only
where the value is missing.
fn orElse
fn orElse(fallback: lazy Value): Value
The value, or the fallback where there is none. This is ??.
trait Indexed
trait Indexed<Key, Value>
a[key]
fn get
fn get(key: Key): Value?
The value at the key, or None if there is none. This is what get on a Map or a List calls.
fn at
fn at(key: Key): Value
The value at the key. This is a[key].
List, Array and Map answer with a message of their own - the index and the length, the key - and this
default is what a type of the program gets that writes no at.
Panics
When the key is not there, with the key is not in the collection. That is what a[key] promises -
Indexed.get is the same question with an Option for an answer, for a caller who expects the key to be missing.
trait MutableIndexed
trait MutableIndexed<Key, Value> with Indexed<Key, Value>
a[key] = value. It also makes a[key] a var path: enemies[0].health = 5 and groups[key].append(value)
take the element out, change it and put it back (without a copy).
fn set
var fn set(key: Key, value: Value)
Puts the value at the key, replacing whatever was there. This is a[key] = value.
trait Slice
trait Slice<Index: Compare = Int>
a[from..to]. The slice shares the storage and starts at index 0 again.
It takes Bounds and not one range type, because all five spellings have a meaning here: an end the range leaves
open is the start or the end of the value, which is the receiver's decision and not the range's.
Index is what a position of the value is: an Int for a list, and a TextIndex for a text, whose positions only
the text itself hands out (docs/design/PANICS.md section 4). The range in the brackets is a range of it.
fn slice
fn slice(range: Bounds<Index>): Self
The part of the value the range covers. This is a[from..to].
trait MutableSlice
trait MutableSlice with Slice
a[from..to] = values. It also makes a[from..to] a var path, which is what other languages need a
mutable span for: samples[0..100].sort() and fill(samples[0..100]) work on this part in place.
Open
Whether values may be a different length than the range it overwrites - growing or shrinking the receiver - is
not decided by the trait. It is up to whatever implements it, and callers should check that type's own signature.
fn replace
var fn replace(range: Bounds<Int>, values: Self)
Overwrites the part of the value the range covers with values. This is a[from..to] = values.