Arithmetic & Logical Expressions
Oxygene allows the use of operators to create comparisons, arithmetic expressions and logic expressions. The language has well-defined set of operators for these scenarios, but Types can provide custom implementations for operators, using a technique called Custom Operators, a.k.a. Operator Overloading.
The above operators can be used to compare two operands for equality, non-equality and sort order.
For types that to not provide a custom equality and/or non-equality operator implementation,
≠ will compare the object reference (i.e. identity) of heap based types (such as Classes), and do a memory/value compare for stack-based types (such as Integers, Booleans, Floats, and Records).
If a matching custom
≠ operator is defined on the type of either the left or the right-hand expression, it will be called instead.
≥ operators are only supported if the appropriate custom operator is implemented on one of the types.
var x := 5; var y := 10; if x ≤ 5 then ...
Note : Oxygene supports rich unicode
≠ operators, but also, for backwards compatibility, the double-character
<> spelling. Fire and Water will auto-correct
≠, respectively, and on macOS you can use ⌥<, ⌥> and ⌥= to type these operators directly, as well.
Double Boolean Comparisons
Oxygene provides a convenient short-hand for comparing a value against two boundaries at once, via Double Boolean Comparisons. a double boolean comparisons is true only of both the first and the second hald of the expression is true. It is convenient for testing if a value falls within a range between two values:
var y := 10; if 10 ≤ x ≤ 15 then writeLn("x is between 10 and 15").
The above check essentially expands to
if (10 ≤ x) and (x ≤ 15) then. ...
The above operators are used to carry out mathematical operations on two operands
+evaluates to the sum of two values by adding them.
-evaluates to the difference of two values by subtracting them.
*evaluates to the product of two values by multiplying them.
/evaluates to the fraction of two values by dividing them.
**evaluates to the power of two values.
divalso evaluates to the fraction of two values by dividing them, but always performs an integer division (losing the remainder)
modevaluates to the remainder of two values left over when performing an integer division.
var a := 2+2; // 4 var b := 12+3; // 9 var c := 3*9; // 27 var d := 8/2; // 4 var d := 2**10; // 1024 var d := 10.0/4.0; // 2.5 var d := 10.0 div 4.0; // 2 var d := 10.0 move 4.0; // 2
/ always uses the type of the input values as result type. dividing two integers will always perform an integer division, producing an integer, potentially losing the remainder. If one of the two operands is a float, the result will be a float, as well.
Also note that Oxygene will apply operator precedence (more on that below for combined expressions, according to mathematical rules (
/ tage precedence before
var a := 5 + 10 * 2; // 25 var b := 5 + (10 * 2); // 25 var b := (5 + 10) * 2); // 30
The above operators can be used to combine boolean expressions.
xor are binary operators, which means the take two parameters;
not is a unary prefix operator and takes one parameter to it's right.
true, if both the expression on the left and the one on the right are true.
true, if either one of the expression on the left or the right is true.
true, if only one of the expression on the left or the right is true, but not both.
true, if the value it precedes is
false, otherwise it returns
true. In other words, it reverses or negates the boolean value.
false, only if the expression on the left is
true, but the the expression on the right is not.
var a := x and y; var b := x or y; var c := x xor y; var d := not x; var e := x implies y;
By default, Oxygene will apply, where starting from the left, the compiler will stop evaluating expressions once the outcome of the expression is determined.
For example, if the left-hand side of an
and operation is
false, the result will always be
false. Likewise, if the left-hand side of an
or operation is
true, the result will always be
true. In both cases, evaluation of the right will not be evaluated at all.
Note that different than in many other, especially C-based languages, the logical
xor operators take precedence over comparisons. For this reason, combining multiple comparisons with logical operators will often require parenthesis:
if x > 5 and y < 10 then ... // 🛑 compiler error, because "(5 and y)" would be evaluated first if (x > 5) and (y < 10) then ... // ✅ works!
The save four operators can also be used for bitwise operations on numeric (integer) values. When doing so, they apply above boolean logic on each bit of the numeric value's in-memory representation, with 0 and 1 represening
1for very bit that is
1in both the expression on the left and the one on the right.
1, for every bit that is
1either one of the expression on the left or the right.
1for every bit that is
1in only one of the expression on the left or the right, but not both.
1, for every bit that is
0for every bit that is one. In other words, it inverts the bit mask of the value.
var a := %0000 1100 and $0000 1010; // %0000 1000 var b := %0000 1100 or $0000 1010; // %0000 1110 var c := %0000 1100 and $0000 1010; // %1111 0110 var d := not %0000 1100 // %1111 0011
Nesting Expressions with Parenthesis
Parenthesis allow you to visually enclose sub-expressions in order to indicate the order of precedence in which they will be executed within a larger expression. This is especially helpful when using the arithmetic and logical expressions discussed in this topic, but can also help clarify other more complex expressions.
var x := 3 + 2 * 5 // evaluates to 3 + 10 = 13, as * has precedence over + by default. var x := (3 + 2) * 5 // evaluates to 5 * 5 = 25, as the parenthesis cause the addition to be performed first.
Nullable Types in Expressions
Please refer to the Nullable Types In Expressions topic for some caveats when using expressions that contain potential nil
values. In particular, a
nil value anywhere in an operator expression propagates outwards, potentially turning the entire expression
nil. This can have some unintuitive results when working wit booleans, in particular in combination with the
not operator, where
not nil remains
nil. Also consider .