The template language
Standard functions
Every function expressions can call, with an example of each.
These functions are available in every expression. Each can be called directly or at the end of a pipe: len(xs) and xs |> len are the same. A call is checked when the template is parsed, for the number of arguments it takes and for where lambdas go.
Functions that take a list treat null as an empty list. A function given the wrong kind of value, such as upper(3), is an error when the expression runs, naming the element it's in.
A component's scope can add its own functions with Scope::function("name", |args| …). One with a standard function's name takes its place in that component.
Lists
len
len(list or text) — How many items, or characters.
[3, 1, 2] |> len
⇒ 3first
first(list) — The first item, or null.
["a", "b", "c"] |> first
⇒ "a"last
last(list) — The last item, or null.
["a", "b", "c"] |> last
⇒ "c"contains
contains(list or text, item) — Whether the list has the item, or the text the substring.
["rust", "wasm"] |> contains("wasm")
⇒ trueindex_of
index_of(list, item) — Where the item is, or -1.
["a", "b", "c"] |> index_of("c")
⇒ 2find
find(list, x -> condition) — The first item the condition holds for, or null. The second argument is a lambda of the item, and optionally its index.
[{ n: 1 }, { n: 5 }, { n: 9 }] |> find(x -> x.n > 4)
⇒ { n: 5 }find_index
find_index(list, x -> condition) — Where the first item the condition holds for is, or -1. The second argument is a lambda of the item, and optionally its index.
[4, 8, 15] |> find_index(x -> x > 5)
⇒ 1map
map(list, x -> value) — Each item turned into a value. The second argument is a lambda of the item, and optionally its index.
[1, 2, 3] |> map(x -> x * 10)
⇒ [10, 20, 30]filter
filter(list, x -> condition) — The items the condition holds for. The second argument is a lambda of the item, and optionally its index.
[1, 2, 3, 4] |> filter((x, i) -> i % 2 == 0)
⇒ [1, 3]update_at
update_at(list, i, x -> new) — The list with item i replaced by what the lambda makes of it. The third argument is a lambda of the item.
[{ done: false }, { done: false }] |> update_at(1, t -> { t | done: true })
⇒ [{ done: false }, { done: true }]set_at
set_at(list, i, value) — The list with item i replaced.
["a", "b", "c"] |> set_at(1, "B")
⇒ ["a", "B", "c"]insert_at
insert_at(list, i, value) — The list with the value inserted before item i (at the end when i is past it).
["a", "c"] |> insert_at(1, "b")
⇒ ["a", "b", "c"]remove_at
remove_at(list, i) — The list without item i.
["a", "b", "c"] |> remove_at(0)
⇒ ["b", "c"]reverse
reverse(list or text) — In the opposite order.
[1, 2, 3] |> reverse
⇒ [3, 2, 1]take
take(list, n) — The first n items.
[1, 2, 3, 4] |> take(2)
⇒ [1, 2]drop
drop(list, n) — All but the first n items.
[1, 2, 3, 4] |> drop(2)
⇒ [3, 4]range
range(end) or range(start, end) — The numbers from start (0) up to, not including, end.
range(2, 6)
⇒ [2, 3, 4, 5]any
any(list, x -> condition) — Whether the condition holds for some item. The second argument is a lambda of the item, and optionally its index.
[1, 5, 9] |> any(x -> x > 8)
⇒ trueall
all(list, x -> condition) — Whether the condition holds for every item. The second argument is a lambda of the item, and optionally its index.
[1, 5, 9] |> all(x -> x > 8)
⇒ falsecount
count(list) or count(list, x -> condition) — How many items (the condition holds for). The second argument is a lambda of the item, and optionally its index.
[true, false, true] |> count(x -> x)
⇒ 2sum
sum(list) or sum(list, x -> number) — The total. The second argument is a lambda of the item.
[{ price: 4 }, { price: 6 }] |> sum(x -> x.price)
⇒ 10min
min(list) or min(list, x -> number) — The smallest item (by the lambda's number, when given), or null. The second argument is a lambda of the item.
[{ n: 4 }, { n: 2 }] |> min(x -> x.n)
⇒ { n: 2 }max
max(list) or max(list, x -> number) — The largest item (by the lambda's number, when given), or null. The second argument is a lambda of the item.
[3, 9, 4] |> max
⇒ 9sort
sort(list) — In order: numbers numerically, otherwise by text.
["pear", "apple", "fig"] |> sort
⇒ ["apple", "fig", "pear"]sort_by
sort_by(list, x -> key) — In order of a key. The second argument is a lambda of the item.
[{ name: "Zoe" }, { name: "Ann" }] |> sort_by(p -> p.name) |> map(p -> p.name)
⇒ ["Ann", "Zoe"]group_by
group_by(list, x -> key) — Records of key and items, in order of first appearance. The second argument is a lambda of the item.
[{ k: "a", n: 1 }, { k: "b", n: 2 }, { k: "a", n: 3 }] |> group_by(x -> x.k) |> map(g -> g.key + ": " + text(g.items.len))
⇒ ["a: 2", "b: 1"]unique
unique(list) — Without repeats, keeping the first of each.
[1, 2, 1, 3, 2] |> unique
⇒ [1, 2, 3]flatten
flatten(list of lists) — One list of every item.
[[1, 2], [3], []] |> flatten
⇒ [1, 2, 3]join
join(list) or join(list, separator) — The items as text, between separators (", ").
["a", "b", "c"] |> join(" · ")
⇒ "a · b · c"Text
upper
upper(text) — In capitals.
"weft" |> upper
⇒ "WEFT"lower
lower(text) — In lower case.
"WEFT" |> lower
⇒ "weft"trim
trim(text) — Without spaces at either end.
" spaced " |> trim
⇒ "spaced"split
split(text, separator) — The pieces between separators.
"a,b,c" |> split(",")
⇒ ["a", "b", "c"]starts_with
starts_with(text, prefix) — Whether the text starts with the prefix.
"/blog/post" |> starts_with("/blog/")
⇒ trueends_with
ends_with(text, suffix) — Whether the text ends with the suffix.
"photo.png" |> ends_with(".png")
⇒ truereplace
replace(text, from, to) — Every from replaced by to.
"a-b-c" |> replace("-", " ")
⇒ "a b c"slice
slice(list or text, start) or slice(…, start, end) — The items or characters from start up to end.
"Weft reference" |> slice(0, 4)
⇒ "Weft"pad_start
pad_start(text, length) or pad_start(text, length, fill) — Filled at the start (with spaces) to a length.
"7" |> pad_start(3, "0")
⇒ "007"Numbers
round
round(n) or round(n, decimals) — Rounded to whole numbers, or decimals.
3.14159 |> round(2)
⇒ 3.14floor
floor(n) — Rounded down.
3.7 |> floor
⇒ 3ceil
ceil(n) — Rounded up.
3.2 |> ceil
⇒ 4abs
abs(n) — Without its sign.
-4 |> abs
⇒ 4clamp
clamp(n, low, high) — Kept between low and high.
120 |> clamp(0, 100)
⇒ 100format_number
format_number(n) or format_number(n, decimals) — With thousands separators: 1,234.50.
1234.5 |> format_number(2)
⇒ "1,234.50"percent
percent(fraction) or percent(fraction, decimals) — 0.425 as "43%".
0.425 |> percent
⇒ "43%"Records
keys
keys(record) — Its field names, in order.
{ b: 2, a: 1 } |> keys
⇒ ["a", "b"]values
values(record) — Its field values, in order of name.
{ b: 2, a: 1 } |> values
⇒ [1, 2]get
get(record, name) — A field by name, or null.
{ title: "Hi" } |> get("title")
⇒ "Hi"has
has(record, name) — Whether it has the field.
{ title: "Hi" } |> has("author")
⇒ falsemerge
merge(record, other) — The fields of both; the other's win.
{ a: 1, b: 2 } |> merge({ b: 3 })
⇒ { a: 1, b: 3 }Values
default
default(value, fallback) — The fallback when the value is null or empty text.
"" |> default("untitled")
⇒ "untitled"is_null
is_null(value) — Whether the value is null.
null |> is_null
⇒ truetype_of
type_of(value) — "null", "text", "number", "bool", "list" or "record".
[1] |> type_of
⇒ "list"text
text(value) — The value as text, as interpolation shows it.
3.5 |> text
⇒ "3.5"number
number(value) — The value as a number, or null.
"42" |> number
⇒ 42