This page lists Expr operators and their direct behavior.
Operator precedence, associativity, grouping, and evaluation order are covered in the next chapter: Expression rules.
Arithmetic operators calculate numeric results. The + operator can also concatenate strings.
| Operator | Meaning | Notes |
|---|---|---|
| + | add or concatenate | numeric add for two numbers; string concatenation if a string is involved |
| - | subtract | numeric operands required |
| * | multiply | numeric operands required |
| / | divide | numeric operands required; division by zero is an error |
| % | modulo | numeric operands required; modulo by zero is an error |
| ** | power | numeric operands required |
Examples:
2 + 3; // 5 7 % 4; // 3 2 ** 3; // 8 'A' + 10; // 'A10'
Notes:
Examples of invalid arithmetic:
10 / 0; // error 10 % 0; // error none() + 1; // error
When the host enables named-operator compatibility mode, these named forms are accepted:
| Named operator | Symbol operator |
|---|---|
| DIV | / |
| MOD | % |
Named operators are case-insensitive when enabled.
10 DIV 2; // 5 10 MOD 3; // 1
Named operators are a compatibility feature. Do not assume they are enabled in all Expr contexts.
The + operator concatenates when a string is involved.
'Tool ' + 3; // 'Tool 3' 'X=' + 10 + ', Y=' + 20;
Concatenation is evaluated left to right according to normal operator rules.
1 + 2 + ' mm'; // '3 mm' 'Value: ' + 1 + 2; // 'Value: 12'
Use parentheses when you want a calculation before concatenation:
'Value: ' + (1 + 2); // 'Value: 3'
Other arithmetic operators do not parse numeric strings automatically.
'10' * 2; // error '10'.parse_num() * 2; // 20
Comparison operators compare values and produce a boolean-style numeric result.
| Operator | Meaning | Notes |
|---|---|---|
| == | equal | no cross-type equality coercion |
| != | not equal | no cross-type equality coercion |
| > | greater than | numeric operands required |
| >= | greater than or equal | numeric operands required |
| < | less than | numeric operands required |
| <= | less than or equal | numeric operands required |
Examples:
5 == 5; // true 5 != 3; // true 3 < 7; // true
Equality does not convert between different value types.
1 == '1'; // false 1 != '1'; // true
Convert explicitly when needed:
'1'.parse_num() == 1; // true
Relational operators require numeric operands.
5 > 3; // true '5' > 3; // error
When named-operator compatibility mode is enabled, these forms are accepted:
| Named operator | Symbol operator |
|---|---|
| EQ | == |
| NE | != |
| GT | > |
| GE | >= |
| LT | < |
| LE | <= |
Named operators are case-insensitive when enabled.
Logical operators use truthiness rules. See Type system for exact truthiness behavior.
| Operator | Meaning | Notes |
|---|---|---|
| ! | logical NOT | unary operator |
| && | logical AND | short-circuits |
| || | logical OR | short-circuits |
| ^^ | logical XOR | evaluates both operands |
Examples:
!0; // true 1 && 0; // false 0 || 5; // true 1 ^^ 1; // false
&& short-circuits. If the left side is false, the right side is not evaluated.
0 && fail(); // fail() is not called
|| short-circuits. If the left side is true, the right side is not evaluated.
1 || fail(); // fail() is not called
^^ is logical XOR. It does not short-circuit because both sides are needed to determine the result.
When named-operator compatibility mode is enabled, these forms are accepted:
| Named operator | Symbol operator |
|---|---|
| NOT | ! |
| AND | && |
| OR | || |
| XOR | ^^ |
Named operators are case-insensitive when enabled.
Bitwise operators operate on integer-style numeric values.
| Operator | Meaning | Notes |
|---|---|---|
| ~ | bitwise NOT | unary operator |
| & | bitwise AND | finite numeric operands required |
| | | bitwise OR | finite numeric operands required |
| ^ | bitwise XOR | finite numeric operands required |
| << | left shift | finite numeric operands required |
| >> | right shift | finite numeric operands required |
Examples:
5 & 3; // 1 5 | 2; // 7 5 ^ 1; // 4 1 << 3; // 8 8 >> 2; // 2
Notes:
Invalid examples:
nan() & 1; // error 1 << 64; // error 1 >> -1; // error
Unary operators apply to one operand.
| Operator | Meaning | Operand rules |
|---|---|---|
| +x | unary plus | numeric operand required |
| -x | unary minus | numeric operand required |
| !x | logical NOT | uses truthiness |
| ~x | bitwise NOT | finite numeric operand required |
Examples:
+a; // numeric identity -a; // numeric negation !a; // logical negation ~a; // bitwise inversion
Unary plus is mostly useful for explicit numeric intent. Unary minus negates numeric values.
value = -10; result = -value; // 10
Assignment and update operators modify variables.
| Operator | Meaning | Notes |
|---|---|---|
| = | assignment | right-associative |
| += | add and assign | uses normal + behavior |
| -= | subtract and assign | numeric update |
| *= | multiply and assign | numeric update |
| /= | divide and assign | numeric update; division by zero is an error |
| %= | modulo and assign | numeric update; modulo by zero is an error |
| **= | power and assign | numeric update |
| &= | bitwise AND and assign | finite numeric operands required |
| |= | bitwise OR and assign | finite numeric operands required |
| ^= | bitwise XOR and assign | finite numeric operands required |
| <<= | shift left and assign | finite numeric operands required |
| >>= | shift right and assign | finite numeric operands required |
| ++x | pre-increment | modifiable numeric variable required |
| x++ | post-increment | modifiable numeric variable required |
| --x | pre-decrement | modifiable numeric variable required |
| x-- | post-decrement | modifiable numeric variable required |
Examples:
a = 5; a += 2; // 7 a *= 3; // 21
Increment and decrement examples:
a = 5; ++a; // 6 a++; // returns old value, then increments --a; a--;
Notes:
Logical compound assignment operators are not part of Expr syntax:
a &&= b; // not supported a ||= b; // not supported a ^^= b; // not supported
Assignment behavior is documented in detail in Variables and assignment.
The conditional operator chooses one of two expressions.
condition ? whenTrue : whenFalse
Example:
result = (a > 0) ? 'POS' : 'NEG';
The condition is evaluated using truthiness rules.
Only the selected branch is evaluated.
result = ready ? UseReadyValue() : UseFallbackValue();
If `ready` is true, only `UseReadyValue()` is called. If `ready` is false, only `UseFallbackValue()` is called.
The conditional operator is right-associative. See Expression rules for precedence and grouping details.
Some operators also have named forms when the host enables named-operator compatibility mode.
Named forms include:
Named operators are compatibility syntax. Prefer symbolic operators in normal Expr scripts unless the host context requires named forms.
'10' * 2; // error
Use explicit parsing:
'10'.parse_num() * 2;
1 == '1'; // false
Convert explicitly if needed:
1 == '1'.parse_num();
nan() & 1; // error
Check first when input may be invalid:
if(value.is_num_notnan()) { result = value & 1; };
^^ evaluates both operands. Do not use it to guard unsafe expressions.
valid ^^ dangerousCall();
Use && or || when you need short-circuit behavior.
Previous: Variables and assignment
Next: Expression rules