the lumen language

comments start with //. semicolons are optional. only false and nil are falsy.

start here: working with data

Four beginner lessons: JSON, sorting, searching and maps.

open the data lesson →

variables

try it →

declare with let, update with =, += or -=.

let score = 10
score += 5
print(score)

functions

try it →

the last line is returned automatically. return also works.

fn square(x) { x * x }
let twice = fn(f, x) { f(f(x)) }
print(twice(square, 3))

pipes |>

try it →

a |> f(b) means f(a, b). great for transforming data.

"hello lumen" |> upper |> print

if is an expression

try it →

use it anywhere a value is expected.

let age = 20
let label = if age >= 18 { "adult" } else { "minor" }
print(label)

for … in walks lists, strings and maps. while loops until false. break exits; continue skips to the next iteration.

for n in range(1, 6) {
  if n % 2 == 0 { continue }
  print(n)
}

lists & maps

try it →

index with [i] (negative counts from the end) or .key for maps.

let xs = [3, 1, 2]
push(xs, 9)
print(xs[-1], len(xs))
let p = { x: 1, y: 2 }
p.x = 10
print(p)

json_parse(text) reads JSON; json_stringify(value) writes it. invalid JSON, functions and circular data report errors.

let data = json_parse("{\"scores\":[12,3,25,8]}")
let best = data.scores |> sort |> reverse |> slice(0, 2)
print(json_stringify({ best: best }))

sorting & slicing

try it →

sort(list) returns a new list: numeric for numbers, lexical for strings. a comparator returns negative, zero or positive. slice(value, start, end) excludes end; negative bounds count from the end.

let xs = [10, 2, 7, 1]
print(sort(xs), xs)
print(sort(xs, fn(a, b) { b - a }))
print(slice("lumen", 0, 3))

search & predicates

try it →

find(list, predicate) returns the first match or nil. any and every stop as soon as the result is known. predicates receive the value and its index.

let xs = [1, 4, 8]
print(find(xs, fn(n) { n > 3 }))
print(any(xs, fn(n) { n > 5 }))
print(every(xs, fn(n) { n > 0 }))

map tools

try it →

values(map) returns values; entries(map) returns [key, value] pairs. has(map, key) checks presence, including keys whose value is nil.

let versions = { lumen: 1, tools: 2 }
print(values(versions))
for pair in entries(versions) { print(pair[0], pair[1]) }
print(has(versions, "lumen"))

string tools

try it →

trim cuts surrounding space, replace swaps every match, includes / starts_with / ends_with search text (includes also searches lists), count(list, predicate) counts matches.

let shout = "  hello lumen  " |> trim |> upper
print(shout)
print(replace("a-b-c", "-", " + "))
print(includes("glow", "low"), includes([1, 2, 3], 2))
print(count(split("the glow of the code", " "), fn(w) { w == "the" }))

list reshaping

try it →

unique removes duplicates, flatten unwraps one level of nested lists, zip pairs two lists up to the shorter one. pow and clamp cover the math.

print(unique([1, 2, 2, 3, 1]))
print(flatten([[1, 2], [3], [4, 5]]))
print(zip(["a", "b", "c"], [1, 2, 3]))
print(pow(2, 10), clamp(7, 0, 5))

built-in functions

46 functions, always available:

print()len()range()map()filter()reduce()push()pop()join()split()reverse()sum()keys()str()num()type()upper()lower()sqrt()floor()round()abs()max()min()random()json_parse()json_stringify()sort()slice()find()any()every()values()entries()has()trim()replace()includes()starts_with()ends_with()unique()flatten()zip()count()pow()clamp()