Skip to content

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
  ⇒ 3

first

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")
  ⇒ true

index_of

index_of(list, item) — Where the item is, or -1.

["a", "b", "c"] |> index_of("c")
  ⇒ 2

find

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)
  ⇒ 1

map

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)
  ⇒ true

all

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)
  ⇒ false

count

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)
  ⇒ 2

sum

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)
  ⇒ 10

min

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
  ⇒ 9

sort

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/")
  ⇒ true

ends_with

ends_with(text, suffix) — Whether the text ends with the suffix.

"photo.png" |> ends_with(".png")
  ⇒ true

replace

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.14

floor

floor(n) — Rounded down.

3.7 |> floor
  ⇒ 3

ceil

ceil(n) — Rounded up.

3.2 |> ceil
  ⇒ 4

abs

abs(n) — Without its sign.

-4 |> abs
  ⇒ 4

clamp

clamp(n, low, high) — Kept between low and high.

120 |> clamp(0, 100)
  ⇒ 100

format_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")
  ⇒ false

merge

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
  ⇒ true

type_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