tur/forms/operators
arithmetic, comparison, logical and bitwise operators.
The compiler implements these itself (src/compiler/builtins.c), so every program has them and there is nothing to import. This file is reference only: it declares nothing the compiler reads.
An operator picks its overload from the type of its FIRST argument, and every other argument must have that type. There is no implicit int-to-float promotion: (+ 1 2.5) is TUR-E0042. Convert first with int->float / float->int (tur/math).
In the signatures, N stands for any numeric kind -- int (64-bit signed), float (64-bit), float32, or a sized integer (int8 int16 int32 uint8 uint16 uint32 uint64). Integer arithmetic wraps on overflow (two's complement) at the kind's own width, whether or not the result is stored: (+ 200u8 100u8) is 44. For a type with no builtin row, + - * / fall back to its Num instance (tur/typeclass); see numeric-tower-guide.
+
(+ [a :N b :N & more :N] :N)
add numbers, left to right.
Takes two or more arguments. On a type with a Num instance and no builtin row, (+ a b c) is (add (add a b) c).
| a | the first addend; its type selects the overload | |
| b | the second addend, of the same type | |
| more | further addends, of the same type |
The sum, of the arguments' type.
(+ 1 2 3) ; => 6 (+ 1.5 2.25) ; => 3.75
-
(- [a :N & more :N] :N)
subtract numbers left to right, or negate one.
With two or more arguments, (- a b c) is (a - b) - c. With one, (- x) is x negated: a float keeps the sign of zero ((- 0.0) is -0.0, which (- 0.0 x) is not), and an integer wraps at its kind's width ((- min-int) is min-int, (- 1u8) is 255). On a type with a Num instance, (- x) is its neg.
| a | the minuend, or the value to negate; its type selects the overload | |
| more | the subtrahends, of the same type |
The difference, or the negation, of the arguments' type.
(- 10 3 2) ; => 5 (- 7.5 0.25) ; => 7.25 (- 7.1) ; => -7.1
*
(* [a :N b :N & more :N] :N)
multiply numbers, left to right.
| a | the first factor; its type selects the overload | |
| b | the second factor, of the same type | |
| more | further factors, of the same type |
The product, of the arguments' type.
(* 2 3 4) ; => 24 (* 1.5 2.5) ; => 3.75
/
(/ [a :N b :N] :N)
divide two numbers.
Exactly two arguments. Integer division truncates toward zero, and an integer division by zero prints division by zero and aborts the program. Dividing the smallest int by -1 wraps, like + - *: the quotient stays that smallest value instead of trapping. Float division follows IEEE 754: dividing by zero gives inf, -inf or nan, with no check.
| a | the dividend; its type selects the overload | |
| b | the divisor, of the same type |
The quotient, of the arguments' type.
(/ 7 2) ; => 3 (/ -7 2) ; => -3 (/ 7.5 2.0) ; => 3.75 (/ 1.0 0.0) ; => inf
mod
(mod [a :int b :int] :int)
the remainder of an integer division.
Integer kinds only (int and the sized integers); (mod 7.5 2.0) is TUR-E0006. The result has the sign of the dividend, as C's % does, so (mod -7 3) is -1, not 2. A zero divisor prints modulo by zero and aborts the program (an error under --interpret), and (mod a -1) is 0 for every a, the smallest int included.
| a | the dividend | |
| b | the divisor, of the same type |
a minus (* (/ a b) b).
(mod 7 3) ; => 1 (mod -7 3) ; => -1 (mod 7 -1) ; => 0
=
(= [a :T b :T] :bool)
are two values equal?
Defined on the numeric kinds, bool, and Sym (keywords such as :a, compared by identity). Not on cstr -- use cstr-eq? -- and not on structs or ADTs: = does not dispatch to Eq; call eq? for those. Floats compare by IEEE 754, so a nan equals nothing, itself included.
| a | the first value | |
| b | the second value, of the same type |
true when they are equal.
(= 3 3) ; => true (= 1.5 2.5) ; => false (= :a :a) ; => true
not=
(not= [a :T b :T] :bool)
are two values different?
The negation of =, on the same types.
| a | the first value | |
| b | the second value, of the same type |
true when they are not equal.
(not= 1 2) ; => true (not= :a :a) ; => false
<
(< [a :N b :N] :bool)
is a less than b?
Numeric kinds only, and exactly two arguments: (< 1 2 3) is TUR-E0006, write (and (< 1 2) (< 2 3)).
| a | the left operand | |
| b | the right operand, of the same type |
true when a < b.
(< 1 2) ; => true (< 2.5 1.5) ; => false
>
(> [a :N b :N] :bool)
is a greater than b?
Numeric kinds only, exactly two arguments.
| a | the left operand | |
| b | the right operand, of the same type |
true when a > b.
(> 2 1) ; => true (> 1.5 2.5) ; => false
<=
(<= [a :N b :N] :bool)
is a less than or equal to b?
Numeric kinds only, exactly two arguments.
| a | the left operand | |
| b | the right operand, of the same type |
true when a <= b.
(<= 2 2) ; => true (<= 3 2) ; => false
>=
(>= [a :N b :N] :bool)
is a greater than or equal to b?
Numeric kinds only, exactly two arguments.
| a | the left operand | |
| b | the right operand, of the same type |
true when a >= b.
(>= 2 2) ; => true (>= 1 2) ; => false
and
(and [a :bool b :bool & more :bool] :bool)
logical and, short-circuiting.
Takes two or more bools and evaluates them left to right, stopping at the first false; the rest are not evaluated. Only bool -- an int is not truthy, (and 1 0) is TUR-E0006.
| a | the first condition | |
| b | the second condition | |
| more | further conditions |
true when every argument is true.
(and true false) ; => false (and (< 1 2) (< 2 3) (< 3 4)) ; => true (and false (= (/ 1 0) 0)) ; => false
or
(or [a :bool b :bool & more :bool] :bool)
logical or, short-circuiting.
Takes two or more bools and evaluates them left to right, stopping at the first true; the rest are not evaluated.
| a | the first condition | |
| b | the second condition | |
| more | further conditions |
true when any argument is true.
(or false true) ; => true (or true (= (/ 1 0) 0)) ; => true
not
(not [b :bool] :bool)
logical negation.
Only bool: (not 0) is TUR-E0006.
| b | the condition to negate |
true when b is false.
(not true) ; => false (not (= 1 2)) ; => true
+.
(+. [a :float b :float & more :float] :float)
add floats.
+ restricted to float: an int (or float32) argument is TUR-E0006 instead of selecting integer arithmetic. Use it where the checker should insist the operands are floats.
| a | the first addend | |
| b | the second addend | |
| more | further addends |
The sum.
(+. 1.5 2.25) ; => 3.75
-.
(-. [a :float & more :float] :float)
subtract floats, or negate one.
- restricted to float; see +.. (-. x) is x negated.
| a | the minuend, or the value to negate | |
| more | the subtrahends |
The difference, or the negation.
(-. 7.5 0.25) ; => 7.25 (-. 7.1) ; => -7.1
*.
(*. [a :float b :float & more :float] :float)
multiply floats.
* restricted to float; see +..
| a | the first factor | |
| b | the second factor | |
| more | further factors |
The product.
(*. 1.5 2.5) ; => 3.75
/.
(/. [a :float b :float] :float)
divide floats.
/ restricted to float; IEEE 754, so a zero divisor gives inf or nan. See +..
| a | the dividend | |
| b | the divisor |
The quotient.
(/. 7.5 2.0) ; => 3.75
bit-and
(bit-and [a :int b :int] :int)
bitwise and of two integers.
Defined on every integer kind; both arguments have the same kind.
| a | the first operand | |
| b | the second operand |
The bits set in both.
(bit-and 12 10) ; => 8
bit-or
(bit-or [a :int b :int] :int)
bitwise or of two integers.
Defined on every integer kind; both arguments have the same kind.
| a | the first operand | |
| b | the second operand |
The bits set in either.
(bit-or 12 10) ; => 14
bit-xor
(bit-xor [a :int b :int] :int)
bitwise exclusive or of two integers.
Defined on every integer kind; both arguments have the same kind.
| a | the first operand | |
| b | the second operand |
The bits set in exactly one.
(bit-xor 12 10) ; => 6
bit-shl
(bit-shl [a :int n :int] :int)
shift an integer left.
Defined on every integer kind. Bits shifted past the top are lost. A shift count that is negative or not less than the width is undefined, as in C. The right shift, bit-shr, is in tur/bits.
| a | the value to shift | |
| n | how many bit positions |
a shifted left by n, zero-filled.
(bit-shl 1 4) ; => 16