Function Reference
Beyond arithmetic and comparisons, an expression can call functions to do more: count a list, check whether text contains a word, keep only the items that match a rule, or format a phone number. This page lists the functions commonly available. The builder also offers a function picker, which is the authoritative, up-to-date list while you are editing an expression.
Functions come in two flavors. Standard functions are the general-purpose tools that come with the expression language. Custom functions are extras built specifically for Gail workflows, like formatting a phone number.
How functions are written
A function name is followed by its inputs in parentheses. Some functions are written after the value they act on, joined by a dot, which reads naturally:
Function names use camelCase (for example startsWith, endsWith), while the
values you reference use lowercase names with underscores (for example
node.contact_phone). The two styles sit together cleanly, so
normalizePhoneNumber(node.contact_phone) reads without confusion.
Standard functions
A selection of the general-purpose functions you will reach for most often:
With map and filter, the first name in the parentheses (like q or n)
stands for the current item as the function walks the list.
Custom functions
normalizePhoneNumber
Formats a phone number into the standard international format (like
+442083661177). Give it the number and a two-letter country code so it knows
how to read a local number.
This is handy for tidying up phone numbers before you store them or pass them to a call or messaging step, so they are all in a consistent shape.
The number has to belong to the country code you give. A number already written
with a leading + for a different country fails rather than coming back
unchanged, so normalizePhoneNumber("+447700900123", "US") is an error.
Falling back instead of failing
Add a third input to get a fallback value back for a number that cannot be read, instead of stopping the run:
This matters most when you tidy a whole list at once, for example every phone
number in an uploaded contact file with a
Map. Without a fallback,
one bad number fails the entire list. With one, the bad rows come out as the
fallback value and you can filter them out in a later step. An empty text "" is
a good choice, because a real formatted number is never empty.
Only the number falls back. A country code that is not valid still fails, because that is a mistake in the workflow rather than in the data.
replace
Replaces every occurrence of one piece of text with another. Give it a count as a third input to replace only the first few, left to right.
Replacing with empty text removes the piece, which is the usual way to clean up a value before sending it somewhere:
The text to look for cannot be empty.
regexReplace
Replaces every match of a pattern, for clean-ups that a plain replace cannot
express in one step. Use $1, $2, and so on in the replacement to put back part
of what the pattern matched:
To write a literal dollar sign in the replacement, write it twice: $$.
Most pattern features work: character classes, \s, \d, \b, alternation,
anchors, and quantifiers. Look-ahead, look-behind, and back-references are not
supported, and a pattern that uses them fails with an error that names the
unsupported part.
first and last
Return the first or last item of a list, without writing the list’s name twice to work out its position:
The item comes back as it is, so you can keep reading fields from it, as with .id
above.
first and last fail on an empty list. If a list can be empty, check its size
first: size(node.quotes.list) > 0 ? node.quotes.list.last().id : "". Do not
compare the result to null instead - that check does not work here.
If a function is given something it cannot handle, such as a phone number it cannot make sense of, the expression fails and the run stops with an error. Feed functions values you expect to be valid, and use a Conditional or Check earlier if you need to guard against bad input.