the ember language
comments start with //. semicolons are optional. only false and nil are falsy.
new to coding?
Start with your first message, then learn variables, choices, loops, functions and pipes.
beginner step-by-step guide →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 ember" |> 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)
loops
try it →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
try it →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("ember", 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 = { ember: 1, tools: 2 } print(values(versions)) for pair in entries(versions) { print(pair[0], pair[1]) } print(has(versions, "ember"))
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 ember " |> 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()