Skip to content

Syntax

The documentation uses explicit declarations:

let x = 5
const y = 7
x: int
x: int = 5
let a, b = 1, 2

Shorthand declarations are also accepted:

x = 5
a, b = 1, 2

Those forms create new variables when the names are not already declared in scope. The docs prefer explicit let because it is easier to scan quickly.

x: int
dist: [long]
adj: [[pair[int, int]]]

The documentation uses fn:

fn solve(n: int) -> int:
n * 2

Shorthand function declarations without fn are also accepted:

solve(n: int) -> int:
n * 2

When a function declares a return type, the last expression in its body is returned automatically. return is still available for early exits.

fn minmax(a: [int]) -> (int, int):
(a.min(), a.max())
fn add_one(&a: [int]) -> void:
for i in [0, len(a)):
a[i] += 1
fn <T> identity(x: T) -> T:
x
@memo
fn fib(n: int) -> long:
if n <= 1: return n
fib(n-1) + fib(n-2)
fn add(a: int, b: int = 1) -> int:
a + b
x = add(4)
y = add(b = 2, a = 4)

Named arguments work for user functions, struct constructors, and helper builtins with optional knobs. The recommended style is to keep the primary data positional and name the option:

st = segtree(a, op = sum)
g = grid_graph(mat, dirs = 8)
pre = prefix(a, op = max)
prod = prefix(a, init = 1, reducer = |acc: int, x: int| acc * x)
struct Point:
x: int
y: int
p = Point(y = 2, x = 1)
@memo
fn fib(n: int) -> long:
if n <= 1: return n
fib(n - 1) + fib(n - 2)
@operator(+)
fn add(a: Point, b: Point) -> Point:
Point(a.x + b.x, a.y + b.y)
@test(input="5\n", expected="25\n")
fn square(x: int) -> int:
x * x
if x > 0:
println "positive"
elif x == 0:
println "zero"
else:
println "negative"
sign = if x > 0 then 1 else if x < 0 then -1 else 0
for i in [0, n): # half-open right
for i in [0, n]: # closed
for i in (0, n): # open both
for i in [0, n, 2): # explicit step
for x in a: # iterate collection
for i, x in a: # index + element
for (u, v) in edges: # destructuring
for x in a where x > 0: # filter

Range notation:

SyntaxMeaning
[a, b)a <= i < b
[a, b]a <= i <= b
(a, b)a < i < b
(a, b]a < i <= b

Step defaults to +1. If lo > hi with no step specified, the inferred step is -1.

while not q.empty():
# ...
while let (d, u) = q:
# loop ends when q is empty
if let (d, u) = pq:
println d
else:
println -1
repeat n:
# body runs n times
defer:
vis = filled(n, false)

defer runs its body when the current scope exits.

for x in a:
guard x > 0
s += x
fn process(x: int) -> int:
if x < 0:
return -1
x * 2

In loops, guard skips to the next iteration. Outside loops, it returns immediately from the current function or top-level program. Use it only in no-value-return contexts.

match x:
case 0: println "zero"
case 1: println "one"
default: println "other"
match:
case x < 0: println "negative"
case x == 0: println "zero"
default: println "positive"
sign = match x:
case 0: 0
case n where n > 0: 1
else: -1
input:
n, m: int
a: [int][n]
input n: int
println x
print a, b, c
println arr
output arr
output arr, sep=" "
newline
each T:
println 1
LevelOperatorsAssociativity
14f(args), a[i], .field, .method(), x++, x--left
13-x, +x, ~xright
12**, **%right
11*, /, %, //, *%left
10+, -, +%, -%left
9<<, >>left
8==, !=, <, <=, >, >=left
7&left
6^left
5|left
4notright
3andleft
2orleft
1? :right
algoMeaning
//floor division (rounds toward negative infinity)
%floor modulo (matches // so that a == (a // b) * b + a % b)
**integer exponentiation
**%modular exponentiation
^bitwise XOR
andlogical AND
orlogical OR
notlogical NOT
+%modular addition
-%modular subtraction
*%modular multiplication
x++postfix increment

=, +=, -=, *=, /=, %=, //=, **=, &=, |=, ^=, <<=, >>=

a < b < c means a < b && b < c. The middle term is evaluated once.

x = a > b ? a : b
a |> sort()
a |> sort() |> println
g.dijkstra(0).dist[n-1] |> println
dp[dimensions] -> type, strategy:
base: dp[...] = val
<- candidate
<- candidate where condition
<- candidate for var in range where condition

Dimension syntax is var: lo..hi with inclusive bounds. Multiple dimensions are comma-separated, for example i: 0..n, j: 0..m.

Supported strategies:

  • maximize
  • minimize
  • sum
  • any
  • assign