LEVIATHAN v962456e · 962456eee1

Declarations

Operator declarations

Define operators on a class or struct by declaring a member with a symbolic selector such as (+), (==) or ([]).

since 0.1.0-alpha.1linuxwindowswasm

Description

A class or struct gives meaning to an operator by declaring a member whose name is the operator in parentheses. The result type comes first and the right-hand operand is the parameter:

Money (+)(Money other) => Money(cents + other.cents);
bool (==)(Money other) => cents == other.cents;

With such a member, a + b calls (+) on a's class, selecting the overload by the type of b. Write the selector without spaces: (==), (<=), ([]). A selector with spaces inside the parentheses declares a member that no expression ever calls.

(==) must return bool. != needs no declaration of its own; it is the negation of ==. Other comparisons are only available if you declare them, and a comparison that is not declared throws a RuntimeException at run time.

Operators on a class

class Money {
    int cents;
    Money (+)(Money other) => Money(cents + other.cents);
    Money (-)(Money other) => Money(cents - other.cents);
    Money (*)(int k) => Money(cents * k);
    bool (==)(Money other) => cents == other.cents;
    bool (<)(Money other) => cents < other.cents;
    string show() => cents.toString() + "c";
}
Money a = Money(150);
Money b = Money(250);
console.writeln((a + b).show());
console.writeln((b - a).show());
console.writeln((a * 3).show());
console.writeln(a == Money(150));
console.writeln(a != b);
console.writeln(a < b);
400c
100c
450c
true
true
true

Rules

  • An operator is a member declared as ReturnType (op)(Type other) body.
  • The operators that can be declared are + - * / % == != < <= > >= << >> ^, and the index operator ([]), which is declared as an accessor (see lang.accessors).
  • A binary expression a op b calls the (op) member of a's class. The right operand's type selects among overloads of the same operator.
  • (==) returns bool. Declaring (==) also provides != as its negation; != can be declared explicitly instead.
  • No other operator is derived from another: declaring (<) does not provide > or <=.
  • A comparison or arithmetic operator that the class does not declare throws a RuntimeException when the expression is evaluated.
  • A struct has a derived == and != when all its fields are comparable (see lang.structs); an explicit (==) replaces the derived one.
  • The selector is written without whitespace inside the parentheses.

Examples

A set of operators that cover the arithmetic and comparison operators:

More operators

class V {
    int n;
    V (/)(int k) => V(n / k);
    V (%)(int k) => V(n % k);
    bool (>)(V o) => n > o.n;
    bool (>=)(V o) => n >= o.n;
    bool (!=)(V o) => n != o.n;
    V (<<)(int k) => V(n << k);
    V (>>)(int k) => V(n >> k);
    V (^)(V o) => V(n + o.n);
}
V a = V(20);
V b = V(7);
console.writeln((a / 4).n);
console.writeln((a % 6).n);
console.writeln(a > b);
console.writeln(a >= b);
console.writeln(a != b);
console.writeln((a << 1).n);
console.writeln((a >> 1).n);
console.writeln((a ^ b).n);
5
2
true
true
true
40
10
27

An operator may be overloaded on the right operand's type:

Overloading an operator by operand type

class Money {
    int cents;
    Money (+)(Money other) => Money(cents + other.cents);
    Money (+)(int extra) => Money(cents + extra);
}
Money a = Money(150);
console.writeln((a + 5).cents);          // 155
console.writeln((a + Money(7)).cents);   // 157
not run — blocked by an open compiler bug

See also

  • Methods and functions — Declare callables with block or single-statement bodies, overloads, default parameters, named arguments and type parameters.
  • Accessors — Replace how a field is read or written with get and set, and define computed values and indexers.
  • Value structs — Declare value types that are copied on every assignment, pass and return, with derived equality and explicit mutating methods.