Operators

Unary operators

-a negates a number.

~a is bitwise negation.
Since this latter is an uncommon operation, it's defined in keen/bits. (Imports will be explained in Modules.)

import keen/bits main void() i int = 1 log -i n nat = 1 log ~n

- doesn't work on nat since that is an unsigned type.
~ doesn't work on int since bitwise operations on signed numbers are confusing.

Defining operators

Operators are just ordinary functions, so you can define them for any type.

main void() a point = 1, 2 log -a point record(x float, y float) to json(a point) ~ - point(a point) -a.x, -a.y

Binary operators

Here are all binary operators and operator-like syntaxes, in order from lowest to highest precedence.
Operators with the same precedence, such as < and >, share a row in the table.

Lower precedence means being less tightly binding.
+ has lower precedence than *, so 1 +2 *3 is 7 because 2 * 3 binds more tightly than 1 + 2.

SyntaxUse
isAsserts that two expressions have the same value.
foo=A function name may end in = , which makes it parse as infix.
elseProvides a default value for an option. See Options.
orTrue if either side is true.
andTrue if both sides are true.
'fooInfix function calls.
fooNormal function calls.
..Creates a range, e.g. 0 .. 10 . The low end is inclusive and the high end is exclusive.
~, ~~Adds one (~) or many (~~) elements to a collection.
==, !=, <, >, <=, >=, <=>Standard comparison operators. All return bool except <=> returns comparison.
|Union (of sets, flags, or bits in a nat).
&Union (of sets, flags, or bits in a nat).
<<, >>Bitshift left and right. These are only defined for nats.
+, -Addition and subtraction.
*, /, %Multiplication, division, and modulo.
**Exponentiation: 2 ** 3 is 8.

As shown above, infix function calls like 'contains have lower precedence than any operator.

main void() log (10 .. 10 + 10 'contains 15)

The above parses like: log ((10 .. (10 + 10)) 'contains 15)

The parentheses around the argument to log are needed because the call to 'contains has lower precedence.

Assignment functions

Function names are allowed to end in an = sign.
If they do, they are always parsed as infix and with an especially low precedence.

main void() # This declares a mutable array. xs nat mut[] = 1, 2, 3 xs ~= 4 xs ~~= 5, 6 xs filter= it.is-even log xs

Binary assignment

Any binary function, including operators, can be combined with the assignment operator := to update a local.

main void() x mut = 3 # Same as `x := x + 2` x +:= 2 log x # Same as `x := x 'min 4` x min:= 4 log x

This works with set-x functions too, such as record field setters.

main void() a mut-point = 1, 1 # Same as `set-x a, a.x * 2` a.x *:= 2 log a.x mut-point record mut x mut float y mut float

Logical "operators"

Unlike the actual operators, these are not functions and can't be overloaded.

!x negates booleans.

and and or work as you would expect. These don't evaluate their right hand side if not necessary.

main void() x nat = 11 log !is-even x # Parentheses are needed because "and" and "or" # have lower precedence than normal functions like "log" log (x > 3 and x < 6 or x > 9 and x < 12)

"is"

is parses with the lowest precedence.
It asserts that the left side is equal to the right side and returns void.

main void() round 1.5 is 2 # is equivalent to: assert (round 1.5) == 2