Operators

Stone uses operators as the primary syntax for arithmetic, comparison, logical, and array operations.

Scalar Arithmetic Operators

For scalar (single number) operations:

OperatorDescription
a + bAddition
a - bSubtraction
a * bMultiplication
a / bDivision
a % bModulo (remainder)
a ^ bPower (exponentiation)

Note: These operators work on scalars only. Using them on arrays will produce an error—use element-wise operators instead.

Element-wise Array Operators

For arrays, use dot-prefixed operators for element-by-element operations:

OperatorDescription
a .+ bElement-wise addition
a .- bElement-wise subtraction
a .* bElement-wise multiplication
a ./ bElement-wise division
a .^ bElement-wise power

Arrays must have matching shapes. These operators also work with scalar-array combinations (broadcasting).

a = [1, 2, 3]
b = [4, 5, 6]

c = a .+ b      // [5, 7, 9]
d = a .* b      // [4, 10, 18]
e = a .^ 2      // [1, 4, 9]

Matrix Operators

OperatorDescription
A @ BMatrix multiplication
A ^ nMatrix power (A must be square)
import eye, transpose from linalg

A = [[1, 2], [3, 4]]
B = [[5, 6], [7, 8]]

C = A @ B           // matrix multiplication
D = transpose(A)    // [[1, 3], [2, 4]]
E = A ^ 2           // A @ A

Comparison Operators

OperatorDescription
a > bGreater than
a < bLess than
a >= bGreater or equal
a <= bLess or equal
a == bEquality
a != bInequality

Logical Operators

OperatorDescription
a && bLogical AND
a || bLogical OR
!aLogical NOT

Pipe Operator

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

OperatorDescription
a |> fPipe: equivalent to f(a)
a |> f(b, c)Pipe with args: equivalent to f(a, b, c)

The pipe operator enables a fluent, left-to-right coding style for function composition:

// Without pipe - nested calls read inside-out
result = h(g(f(x), a))

// With pipe - reads left-to-right
result = x |> f |> g(a) |> h

Pipes are left-associative and have the lowest precedence, so a + b |> f is parsed as (a + b) |> f.

// Transform and process data
data = [1, 2, 3, 4, 5]
result = data |> map(double) |> filter(is_even) |> sum

// Chain string operations
name = "  hello world  " |> trim |> upper |> split(" ")

Unary Operators

OperatorDescription
-aNegation
!aLogical NOT

Precedence

Operators follow this precedence (highest to lowest):

  1. Postfix: member access (.), function calls, indexing ([])
  2. Unary: !, - (negation)
  3. Power: ^, .^ (right-associative)
  4. Multiplicative: *, /, %, .*, ./
  5. Matrix multiplication: @
  6. Additive: +, -, .+, .-
  7. Comparison: >, <, >=, <=
  8. Equality: ==, !=
  9. Logical AND: &&
  10. Logical OR: ||
  11. Pipe: |>

Use parentheses to override precedence when needed.

Examples

// Scalar arithmetic
result = 10 + 5 * 2      // 20 (multiplication first)
result = (10 + 5) * 2    // 30 (parentheses override)
power = 2 ^ 10           // 1024

// Comparison
is_valid = x > 0 && x < 100

// Logical
should_process = is_ready && !is_paused

// Modulo
remainder = 17 % 5       // 2
is_even = n % 2 == 0

// Array operations
xs = [1, 2, 3, 4]
ys = [5, 6, 7, 8]
sums = xs .+ ys          // [6, 8, 10, 12]
products = xs .* ys      // [5, 12, 21, 32]
squares = xs .^ 2        // [1, 4, 9, 16]

// Matrix operations
import transpose from linalg
A = [[1, 2], [3, 4]]
B = [[5, 6], [7, 8]]
C = A @ B                // matrix product
D = transpose(A)         // transpose