Language Tour
A quick tour of Lumen's syntax and features. This page covers all major language constructs with short examples.
Cells (Functions)
Functions in Lumen are called cells:
cell greet(name: String) -> String
return "Hello, {name}!"
endCells support default parameters, named arguments, and expression bodies:
cell power(base: Int, exp: Int = 2) -> Int
let mut result = 1
for _ in 0..exp
result *= base
end
return result
end
cell double(x: Int) -> Int = x * 2Variables and Mutability
let x = 42 # Immutable
let mut counter = 0 # Mutable
counter += 1Destructuring Let
Unpack values directly in let bindings:
let (a, b) = (1, 2) # Tuple destructuring
let [first, second] = [10, 20] # List destructuring
let Point(x, y) = my_point # Record destructuringTypes
Primitive Types
let n: Int = 42
let f: Float = 3.14
let b: Bool = true
let s: String = "hello"
let nothing: Null = nullOptional Type Sugar
T? is shorthand for T | Null:
cell find(items: list[Int], target: Int) -> Int?
for item in items
if item == target
return item
end
end
return null
endThis works in parameter types, return types, let bindings, and record fields.
Union Types
let value: Int | String = 42
let maybe: Int | Null = null # Same as Int?Collections
let numbers: list[Int] = [1, 2, 3]
let scores: map[String, Int] = {"alice": 95, "bob": 87}
let unique: set[Int] = {1, 2, 3}
let pair: tuple[Int, String] = (1, "hello")Records
Records use parentheses for construction:
record Point
x: Float
y: Float
end
let p = Point(x: 1.0, y: 2.0)Property Shorthand
When variable names match field names, use shorthand:
let x = 1.0
let y = 2.0
let p = Point(x, y) # Same as Point(x: x, y: y)Field Constraints
record Product
name: String where length(name) > 0
price: Float where price >= 0.0
endEnums
enum Color
Red
Green
Blue
end
enum Shape
Circle(radius: Float)
Rectangle(width: Float, height: Float)
endType Aliases and Generics
type UserId = String
type Result[T] = result[T, String]
record Box[T]
value: T
endOperators
Arithmetic
let sum = 10 + 5 # Addition
let diff = 10 - 3 # Subtraction
let prod = 4 * 3 # Multiplication
let quot = 10 / 4 # Division
let floor_div = 10 // 3 # Floor division (truncates toward negative infinity)
let rem = 10 % 3 # Modulo
let pow = 2 ** 10 # ExponentiationFloor Division
// performs integer floor division. //= is the compound assignment form:
let x = 7 // 2 # 3
let mut n = 100
n //= 3 # n is now 33Bitwise Operators
let a = 0xFF & 0x0F # AND -> 0x0F
let b = 0xF0 | 0x0F # OR -> 0xFF
let c = 0xFF ^ 0x0F # XOR -> 0xF0
let d = ~0xFF # NOTShift Operators
<< (left shift) and >> (right shift) require Int operands:
let shifted = 1 << 8 # 256
let halved = 256 >> 1 # 128
let flags = 0
let flags = flags | (1 << 3) # Set bit 3
let has_bit = (flags >> 3) & 1 # Check bit 3Compound Assignments
All arithmetic, bitwise, and shift operators have compound forms:
let mut x = 10
x += 5 # x = x + 5
x -= 3 # x = x - 3
x *= 2 # x = x * 2
x /= 4 # x = x / 4
x //= 2 # x = floor(x / 2)
x %= 3 # x = x % 3
x **= 2 # x = x ** 2
x &= 0xFF # x = x & 0xFF
x |= 0x01 # x = x | 0x01
x ^= 0x10 # x = x ^ 0x10String Concatenation
let combined = "Hello" ++ " " ++ "World"Type Operators
is (Type Test)
Returns Bool -- checks if a value is a given type at runtime:
let value: Int | String = 42
if value is Int
print("It's an integer")
endas (Type Cast)
Casts a value to a target type:
let value: Any = 42
let n = value as IntRange Operators
let exclusive = 1..5 # [1, 2, 3, 4]
let inclusive = 1..=5 # [1, 2, 3, 4, 5]Pipe Operator
|> passes the left value as the first argument to the right function:
let result = "data"
|> process()
|> format()
|> validate()Null-Safe Operators
let name = user?.name # Safe access -- null if user is null
let value = maybe ?? 0 # Null coalescing -- 0 if maybe is null
let certain = maybe! # Force unwrap -- panics if nullNull-Safe Index
?[] returns null if the collection is null instead of panicking:
let items: list[Int]? = null
let first = items?[0] # null (no panic)Control Flow
Conditionals
if score >= 90
grade = "A"
else if score >= 80
grade = "B"
else
grade = "F"
endInline if expression:
let max = if a > b then a else bFor Loops
for item in items
print(item)
endFor-Loop Filters
Skip iterations where a condition is false:
for x in numbers if x > 0
print(x) # Only positive numbers
end
for user in users if user.active
process(user)
endLabeled Loops
Use @label for multi-level break/continue:
for @outer row in matrix
for col in row
if col == target
break @outer # Exit both loops
end
end
end
while @retry attempts < max_attempts
if success
break @retry
end
attempts += 1
end
loop @main
if should_stop()
break @main
end
endRange Loops
for i in 1..5
print(i) # 1, 2, 3, 4
end
for i in 1..=5
print(i) # 1, 2, 3, 4, 5
endWhile and Loop
while count < 10
count += 1
end
loop
if done
break
end
endIf Let and While Let
if let Some(value) = maybe
print(value)
end
while let Some(item) = iterator.next()
process(item)
endPattern Matching
Basic Match
match status_code
200 -> return "OK"
404 -> return "Not Found"
_ -> return "Unknown"
endDestructuring Patterns
match point
Point(x: 0, y: 0) -> "origin"
Point(x: x, y: 0) -> "on x-axis"
Point(x: 0, y: y) -> "on y-axis"
Point(x: x, y: y) -> "({x}, {y})"
endGuards
match n
x if x < 0 -> "negative"
0 -> "zero"
x if x < 100 -> "small"
_ -> "large"
endOr Patterns
match c
"a" | "e" | "i" | "o" | "u" -> "vowel"
_ -> "consonant"
endMatch Exhaustiveness
The compiler checks that match statements on enums cover all variants:
enum Direction
North
South
East
West
end
cell describe(d: Direction) -> String
match d
North -> return "up"
South -> return "down"
# Compile error: missing East, West
end
endA wildcard _ or catch-all identifier pattern makes any match exhaustive. Guard patterns do not contribute to exhaustiveness coverage.
Match as Expression
let label = match status
Active -> "active"
Pending -> "pending"
_ -> "other"
endLambdas
let double = fn(x: Int) => x * 2
let add = fn(a: Int, b: Int) => a + b
# Multi-line lambda
let complex = fn(x: Int) -> Int
let doubled = x * 2
return doubled * doubled
endDefer
defer schedules cleanup code to run when the current scope exits:
cell process_file(path: String) -> String
let handle = open(path)
defer
close(handle)
end
# handle is closed automatically when scope exits
return read(handle)
endError Handling
Result Type
cell divide(a: Float, b: Float) -> result[Float, String]
if b == 0.0
return err("Division by zero")
end
return ok(a / b)
end
match divide(10.0, 3.0)
ok(value) -> print("Result: {value}")
err(msg) -> print("Error: {msg}")
endTry Expression
Propagate errors upward:
cell safe_compute(a: Float, b: Float) -> result[Float, String]
let quotient = try divide(a, b)
return ok(quotient * 2.0)
endEffects
Declare side effects in function signatures:
cell fetch(url: String) -> String / {http}
return HttpGet(url: url)
end
cell process(url: String) -> String / {http, llm, trace}
let data = fetch(url)
let summary = Chat(prompt: "Summarize: {data}")
emit("processed")
return summary
endEffects are inferred through call chains and checked at compile time.
Tools and Grants
use tool llm.chat as Chat
use tool http.get as Fetch
grant Chat
model "gpt-4o"
max_tokens 1024
temperature 0.7
grant Fetch
domain "*.example.com"
timeout_ms 5000
bind effect llm to Chat
bind effect http to FetchAgents
agent Assistant
use tool llm.chat as Chat
grant Chat model "gpt-4o"
cell respond(message: String) -> String / {llm}
role system: You are a helpful assistant.
role user: {message}
return Chat(prompt: message)
end
end
cell main() -> String / {llm}
let bot = Assistant()
return bot.respond("Hello!")
endProcesses
Pipeline
pipeline TextProcessor
stages:
-> read
-> clean
-> analyze
cell read(source: String) -> String
return file_read(source)
end
cell clean(text: String) -> String
return text.lower().trim()
end
cell analyze(text: String) -> map[String, Int]
# Count word frequencies
end
endMemory
memory ConversationBuffer
cell main() -> Int
let buffer = ConversationBuffer()
buffer.append("Hello")
buffer.append("Goodbye")
return length(buffer.recent(10))
endMachine (State Machine)
machine OrderWorkflow
initial: Created
state Created(order: Order)
transition Processing(order)
end
state Processing(order: Order)
guard: order.total > 0
transition Shipped(order.tracking)
end
state Shipped(tracking: String)
terminal: true
end
endAsync and Orchestration
# Parallel execution
let results = await parallel for url in urls
fetch(url)
end
# Race for first result
let first = await race
fetch(url_a)
fetch(url_b)
end
# Consensus voting
let answer = await vote
model_a(question)
model_b(question)
model_c(question)
endImports
import math: add, subtract # Named imports
import utils: * # Wildcard import
import helpers: format as fmt # Aliased importDirectives
@strict true # Enable strict mode (default)
@deterministic true # Reject nondeterministic operationsNext Steps
- Basics Tutorial -- Core syntax in depth
- AI-Native Tutorial -- Tools, agents, and workflows
- Language Reference -- Complete specification