Skip to content
kata / a language workbench

Operators

Operators compose expressions. Parentheses make grouping explicit; = is assignment, while == compares values.

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").

LevelForms
PostfixCalls 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.

+, -, *, /, 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) # 14
print((2 + 3) * 4) # 20
print(5 / 2) # 2
print(5.0 / 2.0) # 2.5
print(5 % 2) # 1
print("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.

== 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.

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.

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.