Operators
Operators compose expressions. Parentheses make grouping explicit; = is assignment, while == compares values.
Precedence
Section titled “Precedence”This table runs from tightest binding to loosest. Binary operators at the same level associate to the left. Postfix operations can chain, as in names.get(0).unwrap_or("unknown").
| Level | Forms |
|---|---|
| Postfix | Calls f(...), attributes .name, tuple positions .0, indexing/type arguments [...], construction {...}, ?, ! |
| Prefix | -value, !value |
| Multiplicative | *, /, % |
| Additive | +, - |
| Comparison and interface view | <, >, <=, >=, as |
| Equality | ==, != |
| Logical AND | && |
| Logical OR | ` |
Assignment is a statement form outside this precedence table. Match-arm ->, annotation :, and generic binding @ are punctuation with specific grammatical roles, not arithmetic operators.
Arithmetic
Section titled “Arithmetic”+, -, *, /, and % perform addition, subtraction, multiplication, division, and remainder. Unary - negates a number. + also concatenates strings. With Int operands, division produces an integer; choose a floating-point operand for a fractional result.
print(2 + 3 * 4) # 14print((2 + 3) * 4) # 20print(5 / 2) # 2print(5.0 / 2.0) # 2.5print(5 % 2) # 1print("Kata" + "Script")Arithmetic dispatches through the interpreter’s ops module: add, sub, mul, div, mod, and neg. This is runtime machinery, not a guarantee of user-defined operator overloading. Division by zero and unsupported operand types produce runtime errors.
Comparison
Section titled “Comparison”== and != compare equality. <, >, <=, and >= compare ordering for supported operands. The result is a Bool. Use explicit conjunctions such as 0 <= n && n < 10; comparison chains do not represent a mathematical interval test.
The corresponding ops names are eq, ne, lt, gt, le, and ge. Mixed large-integer/float comparisons have known limits; do not use approximate numeric values to establish exact equality at extreme magnitudes.
Prefix ! negates truthiness and returns a boolean. left && right evaluates right only when left is truthy; otherwise it returns left. left || right evaluates right only when left is falsy; otherwise it returns left. Both short-circuit forms return the selected operand value, which need not be a boolean.
print(!false)print(false && panic("this call is skipped"))print(true || panic("this call is skipped"))print("" || "fallback")Falsy values include nil, false, numeric zero, an empty string, an empty tuple, and a record with no fields. Empty arrays and maps still have record fields and are truthy. Use array.len > 0 or map.len() > 0 to test whether a collection contains elements.
Unwrap and propagate
Section titled “Unwrap and propagate”Postfix value? unwraps a successful Val payload or immediately returns a failure value from the enclosing function. Postfix value! unwraps success or stops with an error on failure. The postfix ! has a different meaning from prefix logical negation.
func answer(): Res[Int, Str] { let value = Res[Int, Str].Val(21)? ret Res[Int, Str].Val(value * 2)}print(answer()!)These operators work with Res, Opt, and supported user-enum shapes. Propagation returns the failure unchanged; the function’s declared return type must accept it. Neither operator catches native runtime errors such as failed string conversion. See results and the result tutorial.
Access and assignment
Section titled “Access and assignment”object.field reads a named field or method. tuple.0 reads a positional tuple element. collection[key] calls the indexing protocol; collection[key] = value writes through its setter protocol. Brackets after a type also apply type arguments: Map[Str, Int].
name = value reassigns a binding. Direct field writes such as point.x = 3 are supported. Nested field assignment is not implemented. See collections for lookup contracts.