Skip to content

Operators ​

This page provides a complete reference for all operators in Tova, organized by category and including a full precedence table.

Arithmetic Operators ​

OperatorNameExampleResult
+Addition3 + 47
-Subtraction10 - 37
*Multiplication4 * 520
/Division10 / 33.333...
%Modulo10 % 31
**Power2 ** 101024

For string concatenation, use + or string interpolation:

tova
"hello" + " " + "world"   // "hello world"
"{first} {last}"           // string interpolation (preferred)

The * operator supports string repetition when used with a string and a number:

tova
"-" * 40    // "----------------------------------------"
"abc" * 3   // "abcabcabc"

Unary - negates a number:

tova
x = 42
y = -x     // -42

Comparison Operators ​

OperatorNameExample
==Equalx == 10
!=Not equalx != 10
<Less thanx < 10
<=Less than or equalx <= 10
>Greater thanx > 10
>=Greater than or equalx >= 10

Chained Comparisons ​

Tova supports chained comparisons, which read naturally as mathematical inequalities:

tova
1 < x < 10          // true when x is between 1 and 10 (exclusive)
0 <= score <= 100    // true when score is in [0, 100]
a < b < c < d        // true when a < b AND b < c AND c < d

Each intermediate value is evaluated only once. Chained comparisons desugar to a conjunction of pairwise comparisons.

Logical Operators ​

Tova provides both keyword and symbolic forms. The keyword forms are idiomatic:

KeywordSymbolMeaningExample
and&&Logical ANDx > 0 and x < 10
or||Logical ORx == 0 or x == 1
not!Logical NOTnot is_empty

Both forms are fully interchangeable:

tova
// Keyword style (preferred)
if is_valid and not is_expired {
  process(item)
}

// Symbol style (also valid)
if is_valid && !is_expired {
  process(item)
}

Logical operators use short-circuit evaluation: and does not evaluate the right operand if the left is falsy, and or does not evaluate the right if the left is truthy.

Membership Operators ​

OperatorMeaningExample
inContained in"a" in list
not inNot contained inx not in banned
tova
if item in allowed_items {
  accept(item)
}

if user not in banned_users {
  grant_access(user)
}

Type Checking Operators ​

OperatorMeaningExample
isType check (true if value is of type)x is String
is notNegated type checkx is not Nil

The is operator tests the runtime type of a value. It works with built-in types and ADT variants:

tova
value = "hello"
value is String       // true
value is Int          // false
value is not Nil      // true
tova
// With ADT variants
result = Ok(42)
if result is Ok {
  print("Success!")
}

option = Some("data")
if option is not None {
  print("Has value")
}

Supported type checks: String, Int, Float, Bool, Nil, Array, Function, Number, and any custom ADT variant name.

Bitwise Operators ​

OperatorNameExample
&Bitwise ANDflags & mask
|Bitwise ORflags | FLAG_READ
^Bitwise XORa ^ b
~Bitwise NOT~mask
<<Left shift1 << 4
>>Right shiftn >> 2
>>>Unsigned right shiftn >>> 1
tova
// Bitwise operations
flags = 0b1010
mask = 0b1100

flags & mask     // 0b1000 (AND)
flags | mask     // 0b1110 (OR)
flags ^ mask     // 0b0110 (XOR)
~flags           // bitwise NOT
1 << 4           // 16 (left shift)
32 >> 2          // 8 (right shift)

Assignment Operators ​

OperatorMeaningEquivalent
=Assignx = 10
+=Add and assignx = x + 10
-=Subtract and assignx = x - 10
*=Multiply and assignx = x * 10
/=Divide and assignx = x / 10
&=Bitwise AND and assignx = x & mask
|=Bitwise OR and assignx = x | flag
^=Bitwise XOR and assignx = x ^ bits
<<=Left shift and assignx = x << n
>>=Right shift and assignx = x >> n
tova
var counter = 0
counter += 1       // counter is now 1
counter *= 5       // counter is now 5

Pipe Operator ​

The pipe operator |> passes the result of the left expression as the first argument to the function on the right:

tova
// Without pipes
var result = format(filter(map(data, transform), predicate))

// With pipes -- reads left to right
result = data
  |> map(transform)
  |> filter(predicate)
  |> format()

Placeholder _ ​

Use _ as a placeholder to control where the piped value is inserted:

tova
10 |> add(_, 5)         // add(10, 5)
"hello" |> replace(_, "l", "r")  // replace("hello", "l", "r")

Method Pipe ​

Use .method() syntax to call a method on the piped value:

tova
items
  |> .filter(fn(x) x > 0)
  |> .map(fn(x) x * 2)
  |> .join(", ")

Range Operators ​

OperatorNameExampleMeaning
..Exclusive range0..50, 1, 2, 3, 4
..=Inclusive range0..=50, 1, 2, 3, 4, 5
tova
for i in 0..10 {       // 0 through 9
  print(i)
}

for i in 1..=100 {     // 1 through 100 (inclusive)
  print(i)
}

Spread Operator ​

The ... spread operator expands an iterable into individual elements:

tova
a = [1, 2, 3]
b = [...a, 4, 5]       // [1, 2, 3, 4, 5]

opts = {color: "red"}
full = {...opts, size: 10}  // {color: "red", size: 10}

It also works in function calls:

tova
args = [1, 2, 3]
sum(...args)            // sum(1, 2, 3)

Optional Chaining ​

The ?. operator accesses a property only if the receiver is not nil:

tova
user?.address?.city     // nil if user or address is nil
items?.length           // nil if items is nil

Nil Coalescing ​

The ?? operator returns the left operand if it is not nil, otherwise the right:

tova
name = user?.name ?? "Anonymous"
port = config?.port ?? 3000

Member Access and Subscript ​

OperatorNameExample
.Member accessuser.name
[]Subscript / indexitems[0]
tova
point.x                 // access field x
matrix[0][1]            // nested indexing
map["key"]              // string subscript

Fat Arrow and Thin Arrow ​

OperatorNameUsage
=>Fat arrowMatch arms, route handlers, short lambdas
->Return typeFunction return type annotations
tova
// Fat arrow in match
match status {
  200 => "OK"
  404 => "Not Found"
  _ => "Unknown"
}

// Thin arrow for return types
fn add(a: Int, b: Int) -> Int {
  a + b
}

Error Propagation Operator ​

The ? postfix operator unwraps a Result or Option, returning early if it contains an error or absence:

tova
fn process(input: String) -> Result<Data, String> {
  parsed = parse(input)?           // returns Err early if parse fails
  validated = validate(parsed)?    // returns Err early if validation fails
  Ok(validated)
}

? on a Result returns the Err value from the enclosing function. ? on an Option returns None. See the Error Handling guide for details.

Await and Yield Operators ​

The await prefix operator suspends execution until an async expression resolves:

tova
async fn main() {
  result = await fetch_data(url)
}

main()

The yield prefix operator produces a value from a generator function. Any function containing yield is automatically treated as a generator — no special syntax is needed. Use yield from to delegate to another generator:

tova
fn range_gen(start, end) {
  for i in start..end {
    yield i
  }
}

fn combined() {
  yield from range_gen(1, 5)
  yield from range_gen(10, 15)
}

Both await and yield have the same precedence as unary - and ... (spread).

Other Operators ​

OperatorNameUsage
:Type annotation / object fieldx: Int, {name: "Alice"}
::Slice step (inside [] only)items[::2], items[1::3]
++String prefix matching (in match patterns only)"api/" ++ rest
?Error propagationparse(input)?

Operator Precedence ​

Operators are listed from highest precedence (binds tightest) to lowest (binds loosest). Operators on the same row have equal precedence.

LevelOperatorsAssociativityDescription
17. ?. [] () ?LeftMember access, optional chain, subscript, call, error propagation
16- (unary) ... (spread) await yieldRightUnary negation, spread, await, yield
15**RightExponentiation
14* / %LeftMultiplication, division, modulo
13+ -LeftAddition, subtraction
12<< >> >>>LeftBitwise shift
11.. ..=NoneRange (exclusive, inclusive)
10in not in is is notNoneMembership test, type checking
9< <= > >= == !=LeftComparison (chainable)
8&LeftBitwise AND
7^LeftBitwise XOR
6|LeftBitwise OR
5not ! ~RightLogical NOT, bitwise NOT
4and &&LeftLogical AND
3or ||LeftLogical OR
2??LeftNull coalescing
1|>LeftPipe

Precedence Examples ​

tova
// Unary - binds tighter than **
-2 ** 3          // (-2) ** 3 = -8
-2 ** 2          // (-2) ** 2 = 4  (not -(2 ** 2) = -4)

// * binds tighter than +
2 + 3 * 4        // 2 + (3 * 4) = 14

// and binds tighter than or
a or b and c     // a or (b and c)

// |> has lowest precedence
data |> f() |> g()  // g(f(data))

// ?? binds tighter than |> but looser than or
a ?? b |> f()    // f(a ?? b)

Released under the MIT License.