Skip to main content

string


title: String sidebar_position: 5

String

Part of the function and operator catalog. Every example shown below is executed as an assertion by the engine's own test suite (examples.test.ts), so a result shown here is a result the engine actually produces for that input.

UPPER

UPPER(text: text) -> text

Converts text to upper case using locale-independent case mapping only — the result never changes with the host's locale, and no locale-sensitive case rule (such as Turkish dotless i) is ever applied.

Examples:

  • UPPER('abc')
    • result: "ABC"
  • UPPER('i')
    • result: "I"

LOWER

LOWER(text: text) -> text

Converts text to lower case using locale-independent case mapping only — the result never changes with the host's locale.

Examples:

  • LOWER('ABC')
    • result: "abc"
  • LOWER('I')
    • result: "i"

TRIM

TRIM(text: text) -> text

Removes leading and trailing whitespace and line terminators. Interior whitespace is left untouched.

Examples:

  • TRIM(' a b ')
    • result: "a b"

SUBSTRING

SUBSTRING(text: text, start: a number, length: a number) -> text

Returns a slice of text: a zero-based start position (in UTF-16 code units) and a length. A negative start counts from the end, consistent with array access. Reaching past the end of the text is an error, not a clamp — bound the call with LENGTH rather than relying on a clamp.

Examples:

  • SUBSTRING('abcdef', 0, 3)
    • result: "abc"
  • SUBSTRING('abcdef', 2, 5)
    • fails with EXPR_STRING_INDEX_OUT_OF_RANGE
  • SUBSTRING('abcdef', -3, 3)
    • result: "def"
  • SUBSTRING('abcdef', -10, 1)
    • fails with EXPR_STRING_INDEX_OUT_OF_RANGE
  • SUBSTRING('abc', LENGTH('abc'), 0)
    • result: ""

SPLIT

SPLIT(text: text, separator: text) -> an array of text

Splits text on a literal separator, returning an array of the pieces between occurrences. The empty text yields a one-element array containing the empty string; two consecutive separators yield an empty element between them. An empty separator is an error — a character-by-character split is a deliberate absence, not an accident.

Examples:

  • SPLIT('a,b,c', ',')
    • result: ["a","b","c"]
  • SPLIT('', ',')
    • result: [""]
  • SPLIT('a,,b', ',')
    • result: ["a","","b"]
  • SPLIT('abc', '')
    • fails with EXPR_TYPE_MISMATCH

REPLACE

REPLACE(text: text, search: text, replacement: text) -> text

Replaces every occurrence of a literal piece of text with another — not only the first occurrence, which is the host language's own default and is deliberately not inherited here. The search text is always literal, never a pattern. An empty search text is an error.

Examples:

  • REPLACE('a-a-a', 'a', 'b')
    • result: "b-b-b"
  • REPLACE('a.b.c', '.', 'X')
    • result: "aXbXc"
  • REPLACE('abc', '', 'X')
    • fails with EXPR_TYPE_MISMATCH

CONCAT

CONCAT(first: text, second: text, ...) -> text

Joins two or more pieces of text together, in order. This is the only way to join text in rule-line: '+' is numeric only, and no argument is ever converted to text on the engine's own initiative — join a number or a date by converting it explicitly first.

Examples:

  • CONCAT('a', 'b')
    • result: "ab"
  • CONCAT('a', 'b', 'c')
    • result: "abc"
  • CONCAT('', '')
    • result: ""
  • CONCAT('a', 1)
    • fails with EXPR_TYPE_MISMATCH

INDEXOF

INDEXOF(text: text, search: text) -> a number

Returns the position (in UTF-16 code units) of the first occurrence of a piece of text, or minus one if it does not occur. Compare the result against minus one before using it as a position — an author guards on the result, rather than the call failing, because INDEXOF is a probe, not a lookup (unlike GET/FIND_BY). See IF's entry for the executable guard idiom.

Examples:

  • INDEXOF('abcabc', 'b')
    • result: "1"
  • INDEXOF('abc', 'z')
    • result: "-1"
  • INDEXOF('abc', '')
    • result: "0"

LASTINDEXOF

LASTINDEXOF(text: text, search: text) -> a number

Returns the position (in UTF-16 code units) of the last occurrence of a piece of text, or minus one if it does not occur. Compare the result against minus one before using it as a position, exactly as INDEXOF's entry describes.

Examples:

  • LASTINDEXOF('abcabc', 'b')
    • result: "4"
  • LASTINDEXOF('abc', 'z')
    • result: "-1"

PADSTART

PADSTART(text: text, targetLength: a number, padText: text) -> text

Pads text on the left with a repeated pad text until it reaches a target length (in UTF-16 code units). If the text is already at or beyond the target length, it is returned unchanged and never truncated. The pad text's last repetition is truncated to land exactly on the target. An empty pad text is an error.

Examples:

  • PADSTART('7', 3, '0')
    • result: "007"
  • PADSTART('abc', 2, '0')
    • result: "abc"
  • PADSTART('1', 5, 'ab')
    • result: "abab1"
  • PADSTART('a', 3, '')
    • fails with EXPR_TYPE_MISMATCH

PADEND

PADEND(text: text, targetLength: a number, padText: text) -> text

Pads text on the right with a repeated pad text until it reaches a target length (in UTF-16 code units). If the text is already at or beyond the target length, it is returned unchanged and never truncated. The pad text's last repetition is truncated to land exactly on the target. An empty pad text is an error.

Examples:

  • PADEND('7', 3, '0')
    • result: "700"
  • PADEND('abc', 2, '0')
    • result: "abc"
  • PADEND('1', 5, 'ab')
    • result: "1abab"
  • PADEND('a', 3, '')
    • fails with EXPR_TYPE_MISMATCH

REPEAT

REPEAT(text: text, count: a number) -> text

Repeats a piece of text a whole number of times. A count of zero yields the empty string; a negative or fractional count is an error; a result longer than rule-line allows fails before anything is built.

Examples:

  • REPEAT('ab', 3)
    • result: "ababab"
  • REPEAT('ab', 0)
    • result: ""
  • REPEAT('ab', -1)
    • fails with EXPR_TYPE_MISMATCH