Help › Expressions · version 5 ·
tags
#help #language
order
40
description
the expression language by example, and every core function

Help: expressions✎ edit

Expressions compute values: in rules, in computed fields (@calc), in object queries (?query=), in ```table fences, and in the Fiddle, where you can try every line below. Each example shows the expression, then its value.

Values✎ edit

  • 42 → 42
  • 2.5 → 2.5
  • "hello" → "hello"
  • 'single quotes too' → "single quotes too"
  • true → true
  • [1, 2, 3] → [1, 2, 3]
  • {a: 1, b: "x"} → {a: 1, b: "x"}
  • null ?? "none" → "none"

Numbers are Int (whole, 64-bit, wraps like Java's long) or Float. Number accepts either. Text is String. Dates and durations have their own types, below.

Arithmetic✎ edit

  • 1 + 2 * 3 → 7
  • (1 + 2) * 3 → 9
  • 99 / 2 → 49.5
  • 4 / 2 → 2.0
  • 7 % 3 → 1
  • 1 + 2.5 → 3.5

/ always gives a Float. Dividing by zero is an error (E_ARITH), never infinity.

Text✎ edit

  • "n=${1 + 2}" → "n=3"
  • "a" + "b" → "ab"
  • "ell" in "hello" → true
  • toUpper("abc") → "ABC"
  • split(s = "a,b,c", by = ",") → ["a", "b", "c"]

Write \${ for a literal ${. Triple quotes ("""…""") hold text over several lines.

Comparing and logic✎ edit

  • 1 is 1 → true
  • 1 is not 2 → true
  • 5 is "5" → false
  • 1 < 2 and 3 > 2 → true
  • false or true → true
  • not false → true
  • 2 in [1, 2] → true
  • 3 not in [1, 2] → true
  • "a" in {a: 1} → true

is and == are the same, as are and/&&, or/||, not/!. and and or take Booleans only: for a default value use ??. Comparisons don't chain: 1 < 2 < 3 is an error.

Missing values✎ edit

  • x ?? 7 → 7
  • x is defined → false
  • x is empty → true
  • [] is empty → true
  • {a: null}.a ?? "none" → "none"

Reading a name that has no value is an error (E_UNDEFINED) unless you test it or give it a default. ?. reads a field of something that may be null.

Choosing✎ edit

  • if 2 > 1 then "yes" else "no" → "yes"
  • (if true then 1 else 2) + 5 → 6

An if in an expression always has an else.

Types and casts✎ edit

  • 5 is a Int → true
  • 5.5 is a Int → false
  • "x" is a String → true
  • "42" as Int → 42
  • 4.9 as Int → 4
  • 12 as String → "12"
  • typeOf(1 + 1) → "Int"

Objects and lists✎ edit

  • {a: 1} + {b: 2} → {a: 1, b: 2}
  • {a: {x: 1}} ++ {a: {y: 2}} → {a: {x: 1, y: 2}}
  • {a: 1, b: 2} - {b: ""} → {a: 1}
  • [1, 2] + 3 → [1, 2, 3]
  • [1] ++ [2] → [1, 2]
  • [1, 2, 3][-1] → 3
  • {"a-b": 2}["a-b"] → 2
  • {a: 5}.a → 5

+ merges objects one level deep (the right side wins); ++ merges all the way down and joins lists. A negative index counts from the end.

Working with lists✎ edit

  • [1, 2, 3] map (x => x * 2) → [2, 4, 6]
  • [1, 2, 3] filter (x => x > 1) → [2, 3]
  • [1, 2, 3] exists (x => x > 2) → true
  • [[1], [2, 3]] flatMap (x => x) → [1, 2, 3]
  • [1, 2, 3] fold (acc = 0) (x => acc + x) → 6
  • [1, 2, 3] mkString ", " → "1, 2, 3"
  • [{id: "a"}, {id: "b"}] indexBy "id" → {a: {id: "a"}, b: {id: "b"}}
  • {a: 1} map (p => p.key + p.value) → ["a1"]
  • ids flatMap par (i => http.json(url = "https://…/" + i)): flatMap, with the web calls running at once, at most 4 at a time (flatMap par 8 (…) for up to 8, at most 32); results stay in the order of ids. map par is the same for map. If one fails, the others finish first, then the error is raised. With nothing to wait for, par changes nothing.
  • [1, 2, 3] filter (x => x > 1) map (x => x * 10) → [20, 30]

The part in parentheses is a small function: x => … takes each item as x. On an object, map, filter and exists see {key, value} pairs.

Patterns✎ edit

  • "/acct/42" matches /\/acct\/(?<id>\d+)/ → true
  • "ab" ~= /a./ → true

A pattern is written between slashes, not quotes. In a rule, named groups like (?<id>…) become variables after a successful match.

Dates and durations✎ edit

  • ("2026-09-24" as Date) < ("2026-09-25" as Date) → true
  • ("2026-09-24T00:00:00Z" as Date) + "2h30m" → "2026-09-24T02:30:00.000Z"
  • ("2026-09-25" as Date) - ("2026-09-24" as Date) → "1d"
  • "90s" as Duration → "1m30s"
  • isoDate("2026-09-24T10:00:00Z" as Date) → "2026-09-24"

A duration is text like "5s", "5 seconds", "2h30m", "1d"; next to a date it's read as a duration. Dates are ISO text when stored.

Core functions✎ edit

Functions take named arguments, split(s = "a,b", by = ","); one that takes a single argument also takes it bare, sizeOf([1, 2]); a variable with the argument's name can stand for it, split(s, by). f(obj...) passes an object's fields as the arguments.

  • sizeOf(x): length of a String or list, number of fields of an object.
  • typeOf(x): the type's name.
  • now(): the current date and time. today(): today at 00:00 UTC.
  • isoDate(d): a Date as YYYY-MM-DD.
  • toMillis(x): a Date or Duration as milliseconds.
  • uuid(): a random id.
  • trim(s), toUpper(s), toLower(s).
  • split(s, by): text to a list.
  • replaceAll(s, regex, with), replaceFirst(s, regex, with): the regex given as text.
  • slice(x, from, until): part of a String or list; until optional, negatives count from the end.
  • range(from, until): the Ints from from up to until - 1.
  • flatten(xs): one level of nested lists.
  • math.sum(xs), math.min(xs), math.max(xs), math.average(xs): over a list of numbers; average is always a Float.
  • nicej(x): pretty JSON text.
  • hashcode(x): a sha1 of the value.
  • urlencode(s), base64encode(s), base64decode(s).
  • json.parse(text): JSON text to a value.
  • csv.parse(text): CSV with a header row to a list of rows; numeric cells become numbers.
  • http.json(url, headers), http.text(url, headers): fetch a web page (https, public sites, 10 s, 2 MB), in rules and flows only: the flow pauses while it waits, and the server carries on. In a computed field, a table or a query it's an error (E_WAIT): fetch in a rule and store the result.

In rules there are also the engine's own messages: log(msg), diesel.throw(code, msg), dom.upsert(cls, entity), dom.find(cls, key), dom.list(cls), dom.remove(cls, key).

When it goes wrong✎ edit

Errors are never silent: they say what went wrong and where. The common ones are E_UNDEFINED (a name with no value: use ?? or is defined), E_TYPE (the wrong kind of value, like "a" or true), E_PARSE (the text isn't an expression), E_ARITH (division by zero), E_ARG (a function's arguments) and E_NO_TOOL (no such function).