Skip to content

Operators And Precedence

Nilakan operators are strict about operand types. Most binary operators parse left-associatively.

From highest precedence to lowest:

| Precedence | Syntax | Notes | | ---------- | ------------------------------------------------- | ---------------------------------------------------- | | 1 | f(...), x.method(...), x[i], x[start:end] | calls, member calls, indexing, slicing | | 2 | try x, -x | error propagation, unary minus | | 3 | *, /, % | multiplication, division, remainder | | 4 | +, - | addition, subtraction, concatenation, set difference | | 5 | & | set intersection | | 6 | ^ | set symmetric difference | | 7 | \| | set union | | 8 | <, <=, >, >=, in, not in | ordering and membership | | 9 | ==, != | equality and inequality | | 10 | not x | boolean negation | | 11 | and | boolean conjunction | | 12 | or | boolean disjunction | | 13 | a if cond else b | conditional expression | | 14 | a catch b | error-value fallback |

Most binary operators parse left-associatively.

value = 10 - 3 - 2

That expression parses as (10 - 3) - 2.

Comparison operators do not chain. Write each comparison explicitly and combine the boolean results with and:

lower = 0
value = 1
upper = 2
inside = lower < value and value < upper

lower < value < upper is a syntax error. Parentheses remain meaningful, so (lower < value) == expected is valid.

Unary try, unary -, and not recurse rightward. Conditional expressions and catch expressions are right-associative.

first = True
second = False
value = "a" if first else "b" if second else "c"

That expression parses as "a" if first else ("b" if second else "c").

and and or evaluate the left operand first and short-circuit when its value determines the result. Other binary operators evaluate both operands before applying the operator.

def expensive() -> bool:
return False
ok = True or expensive()

The call to expensive() is not evaluated because the left operand already makes the result true.

Conditional expressions evaluate the condition first, then only the selected branch.

safe = 1
condition = True
fallback = 0
value = safe if condition else fallback

catch evaluates its left expression first. It evaluates the fallback only for the left expression’s direct-error result. try propagates a direct error within the current function; accepted propagation is reified as a direct return result at the function boundary. Existing propagation bypasses both outer handlers.

Arithmetic uses JavaScript operator behavior, except that non-finite results produce ValueError. In particular, % is JavaScript remainder rather than Python modulo: -7 % 2 evaluates to -1.

items = [1, 2] + [3] * 2
both = {1, 2, 3} & {2, 3}
ok = not False and 2 in items
label = "yes" if ok else "no"
value = [1].get(10) catch 0