User-Defined Operators
Description
Infix operators are defined much like functions:
def (p1: t1) op (p2: t2): rt = ...
For example:
def (a:i32,b:i32) +^ (c:i32,d:i32) = (a+c, b+d)
We can also define operators by enclosing the operator name in parentheses and suffixing the parameters, as an ordinary function:
def (+^) (a:i32,b:i32) (c:i32,d:i32) = (a+c, b+d)
This is necessary when defining a polymorphic operator.
Operator Names and Fixity
A valid operator name is a non-empty sequence of characters chosen from the string "+-*/%=!><&^". The fixity of an operator is determined by its first characters, which must correspond to a built-in operator. Thus, +^ binds like +, whilst *^ binds like *. The longest such prefix is used to determine fixity, so >>= binds like >>, not like >.
Restrictions
It is not permitted to define operators with the names && or || (although these as prefixes are accepted). This is because a user-defined version of these operators would not be short-circuiting. User-defined operators behave exactly like ordinary functions, except for being infix.
Shadowing Built-in Operators
A built-in operator can be shadowed (i.e. a new + can be defined). This will result in the built-in polymorphic operator becoming inaccessible, except through the intrinsics module.
Prefix Notation
An infix operator can also be defined with prefix notation, like an ordinary function, by enclosing it in parentheses:
def (+) (x: i32) (y: i32) = x - y
This is necessary when defining operators that take type or shape parameters.