Expressions
Arithmetic
All arithmetic uses IEEE 754 Decimal128 — no floating-point surprises.
1 + 2 * 3 // 7
10 / 4 // 2.5
0.1 + 0.2 // 0.3 (exact!)
2 ** 10 // 1024
-(3 + 2) // -5Division by zero returns null.
Strings
"hello" + " world" // "hello world"
upper case("hello") // "HELLO"
substring("hello", 2, 3) // "ell"
string length("café") // 4 (Unicode code points)Comparisons
3 > 2 // true
1 = 1.0 // true (integer = decimal)
"a" < "b" // true (lexicographic)
null = null // true
null > 1 // null (undefined ordering)Boolean
true and false // false
true or false // true
not(true) // falseIf-then-else
if score >= 700 then "approved" else "declined"Between
5 between 1 and 10 // true
"b" between "a" and "c" // trueIn expression
3 in [1, 2, 3] // true
"A" in ["A", "B"] // true
5 in [1..10] // true
5 in (1..5) // false (exclusive)Path expressions
{name: "Alice", age: 30}.name // "Alice"
[{a:1},{a:2},{a:3}].a // [1, 2, 3]Filter expressions
[1, 2, 3, 4, 5][item > 3] // [4, 5]
[{a:1},{a:2},{a:3}][a > 1] // [{a:2},{a:3}]
["a","bb","ccc"][string length(item)>1] // ["bb","ccc"]For expressions
for x in [1,2,3] return x * 2 // [2, 4, 6]
for x in 1..5 return x * x // [1, 4, 9, 16, 25]
for x in [1,2], y in [10,20] return x+y // [11, 21, 12, 22]Quantified expressions
some x in [1,2,3] satisfies x > 2 // true
every x in [2,4,6] satisfies even(x) // true
some x in [1,2], y in [3,4] satisfies x+y=5 // trueFunction definitions
(function(x) x * 2)(5) // 10
(function(a, b) a + b)(3, 4) // 7Functions defined in contexts can call themselves recursively:
{
fact: function(n) if n <= 1 then 1 else n * fact(n - 1),
result: fact(5)
}.result
// 120Let expressions
Bind a local variable for use within a scoped body expression. let bindings are not visible outside their body.
let x = 5 in x + 1 // 6
let rate = 0.1 in 1000 * rate // 100
let monthly = annual / 12 in monthly * 3 // (requires annual in context)Bindings can be chained — each binding sees the previous ones:
let base = 100 in
let tax = base * 0.1 in
base + tax
// 110Functions can be bound too:
let double = function(n) n * 2 in
for x in [1, 2, 3] return double(x)
// [2, 4, 6]Use case
let makes complex expressions readable by naming intermediate results — like local variables in a programming language.
Pipeline operator (|>)
Chains operations left-to-right. The left value becomes the first argument of the right function.
"hello" |> upper case // "HELLO"
[1, 2, 3] |> count // 3
[1, 2, 3] |> sum // 6
[1, 2, 3] |> reverse // [3, 2, 1]Use ? as an explicit slot when you need to pass the value to a non-first argument:
"hello world" |> substring(?, 1, 5) // "hello"
"hello" |> contains(?, "ell") // truePipelines chain naturally:
" Hello World " |> trim |> lower case |> upper case
// "HELLO WORLD"
"hello" |> upper case |> substring(?, 1, 3)
// "HEL"Arithmetic executes before |>:
1 + 2 |> string // "3" (same as string(1 + 2))Use case
|> is ideal for data transformation pipelines — applying a sequence of string or list operations without deeply nested function calls.
Instance of
1 instance of number // true
"hello" instance of string // true
[1,2] instance of list<number> // true
null instance of Null // true
1 instance of Any // true