Reference

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.