Expression strings
Expression strings turn arr.ai into a sophisticated text templating engine. Conceptually, they are a simple extension to strings, allowing expressions to be nested inside such strings. In practice, this opens up a rich text formatting system that allows production of very complex output structures, including the arbitrarily deep structures required for code generation.
Basic structure#
Expression strings are like regular strings with three differences:
- Expression strings begin with a
$. The regular string"abc"equals the expression string$"abc". The same applies to single-quoted and backquoted strings. - Expression strings treat whitespace differently than regular strings do.
- Expressions may be embedded within an expression string, allowing for dynamic
content. The expression string
$"id = ${i};"evaluates to"id = 42;"ifiequals 42.
Whitespace rules#
Expression strings apply the following rules to handle whitespace:
If the first character of a string is a newline, it is discarded. This only applies for literal newlines in the source. The
\nescaped form will be retained.Example: The following string equals
"abc".$"abc"After removal of any newlines per the first rule, any leading whitespace up to the first newline or non-whitespace character will be removed. Subsequent occurrences of the same leading whitespace after a newline are also removed.
Example: The following:
$" abc def ghi"produces the following output:
abc defghiIf the last newline (
\n) is followed by pure whitespace, the newline and whitespace are discarded.If, after indentation removal, an embedded expression is the only remaining content on a line, and the formatted result is empty, then the entire line, including any newline at the end, is omitted from the final expression string.
Example: The following expression equals
"abc\ndef":let s = ""; $" abc ${s} def"In contrast, the following expression equals
"abc\n123\ndef"(note the extra\nin the result):let s = "123"; $" abc ${s} def"
Embedded expressions#
Embedded expressions are evaluated and formatted to provide content for the expression strings containing them. Their general form is as follows:
${expr (:format (:sep (:extra)opt)opt)opt}
The elements are as follows:
expr is the expression to be evaluated and formatted. All names in scope for the containing expression string are also in scope for its embedded expressions.
Example:
$"=${6*7}="equals"=42=".If present, format controls the way expr is formatted. It is a printf-style formatting string. If sep is omitted, format is applied to expr directly. If absence,
%vis assumed.Example:
$"=${//math.pi:06.3f}="equals"=03.142=".If sep is present, expr is treated as an array, and format is applied to each element. The formatted results are concatenated, with sep used as a separator between each pair of results.
Example:
$"${[1, 2, 3, 4]>>.^2:02d:--}"equals"01--04--09--16".If extra is present, it is appended to the formatted result, but only if the result is not empty.
Examples:
$"${ [1, 2, 3] :::=}"equals"123="$"${ [1, 2, 3] where .>10 :::=}"equals""
The sep and extra modifiers allow the usual character escapes plus one special escape,
\i, which expands to"\n" ++ indent, whereindentequals the leading whitespace immediately preceding the embedded expression, back to the beginning of the line.Example: The following:
let arr = [1, 2, 3, 4]; $" numbers: ${arr::\i}"produces the following output:
numbers: 1 2 3 4