Operators combine values into new values.
You have already used arithmetic operators such as `+`, `-`, `*`, and `/`.
Conditions use operators to make decisions. They are used by `if`, `while`, `for`, logical expressions, and the conditional operator.
Arithmetic operators work with numbers.
2 + 3; // 5 7 - 4; // 3 6 * 5; // 30 20 / 4; // 5 7 % 4; // 3 2 ** 3; // 8
The `%` operator returns the remainder after division.
10 % 3; // 1
The `**` operator raises a number to a power.
2 ** 4; // 16
Division and modulo by zero are errors.
The `+` operator can also join strings.
'Probe' + ' started';
The result is:
'Probe started'
If a string is involved, `+` creates a string result.
'Tool ' + 5;
This produces:
'Tool 5'
Other arithmetic operators, such as `-`, `*`, `/`, `%`, and `**`, require numbers.
Comparison operators compare values and produce a true or false result.
5 == 5; // true 5 != 3; // true 5 > 3; // true 5 >= 5; // true 2 < 8; // true 2 <= 1; // false
Common comparison operators:
Relational comparisons such as `>`, `>=`, `<`, and `<=` require numbers.
Expr does not treat a number and a string as equal just because they look similar.
1 == 1; // true '1' == '1'; // true 1 == '1'; // false
This is useful because it avoids hidden conversions in machine logic.
Conditions use truth rules.
For numbers:
if(1) { 'runs'; }; if(0) { 'does not run'; };
Expr also supports `true` and `false` literals. They behave like numeric `1` and `0`.
ready = true; blocked = false;
For strings, only the string `'true'` is true in a condition. Other strings are false.
if('true') { 'runs'; }; if('hello') { 'does not run'; };
`none()` and `nan()` are false in conditions.
Logical operators combine conditions.
1 && 1; // true 1 && 0; // false 0 || 1; // true 0 || 0; // false 1 ^^ 0; // true 1 ^^ 1; // false !1; // false !0; // true
Common logical operators:
Use `&&` when all conditions must be true.
toolLoaded = true; probeReady = true; canStart = toolLoaded && probeReady;
Use `||` when at least one condition must be true.
manualMode = false; autoMode = true; canRun = manualMode || autoMode;
Use `!` to invert a condition.
blocked = false; canRun = !blocked;
`&&` and `||` use short-circuit evaluation.
For `&&`, if the left side is false, the right side is not evaluated.
a = 0; b = 0; (a > 0) && (b = 5); b; // 0
Because `a > 0` is false, `(b = 5)` is not executed.
For `||`, if the left side is true, the right side is not evaluated.
a = 1; b = 0; (a > 0) || (b = 5); b; // 0
Short-circuit behavior is useful for guarding logic that should only run when earlier checks pass.
probeEnabled && probeReady;
Expr follows normal operator precedence rules.
Multiplication happens before addition:
2 + 3 * 5; // 17
Parentheses make the order explicit:
(2 + 3) * 5; // 25
Use parentheses when a condition controls machine behavior. Clear code is better than relying on the reader to remember precedence rules.
canProbe = (probeEnabled && probeReady) && !blocked;
Bitwise operators work with integer-like numeric values.
5 & 3; // 1 5 | 2; // 7 5 ^ 1; // 4 1 << 3; // 8 8 >> 2; // 2 ~0; // -1
Common bitwise operators:
Bitwise operators are useful when working with flags, masks, packed values, or low-level numeric data.
Do not confuse bitwise operators with logical operators:
The conditional operator chooses between two values.
result = condition ? valueWhenTrue : valueWhenFalse;
Example:
toolReady = true; message = toolReady ? 'Ready' : 'Not ready';
The value of `message` is `'Ready'`.
For longer logic, use `if`. The conditional operator is best for short value choices.
Compound assignment updates a variable using its current value.
count = 0; count += 1; count += 1; count; // 2
This is the same as:
count = 0; count = count + 1; count = count + 1;
Supported compound assignment operators include:
+= -= *= /= %= **= &= |= ^= <<= >>=
Logical compound assignment is not supported:
a &&= b; // not supported a ||= b; // not supported a ^^= b; // not supported
Read this script and predict the final value:
toolLoaded = true; probeReady = false; blocked = false; canStart = toolLoaded && probeReady && !blocked; canStart;
The final value is `false` because `probeReady` is false.
Now change `probeReady` to `true` and the final value becomes `true`.
Next: Control flow