Interpolation
Strings beginning with $ support interpolation: the expression in a brace hole is evaluated, converted to text, and spliced into the string. Holes are not limited to variables; arithmetic and function calls work too.
Syntax forms
The full form is {expression,alignment:format}: the first , introduces the alignment width, the first : introduces the format spec, and both parts are optional.
Format verbs
A format spec is a verb plus an optional precision digit (as in F2, N0). The verbs share the table with numeric ToString(format); there are four:
| Verb | Meaning | Example | Output |
|---|---|---|---|
F | fixed-point; the digit sets decimal places | {pi:F2} | 3.14 |
N | thousands grouping; the digit sets decimal places (default 2) | {1234567:N0} / {1234567:N} | 1,234,567 / 1,234,567.00 |
X | hexadecimal (integers only); uppercase {n:X} gives 2A, lowercase {n:x} gives 2a | {n:X} | 2A |
P | percentage (times 100 plus %); the digit sets decimal places | {0.25:P0} / {0.5:P1} | 25 % / 50.0 % |
- Format strings render with InvariantCulture and do not vary with the system locale.
- Non-numeric types (strings, bool, Duration, and so on) ignore the format part: for a string,
{s:F2}just prints it as is. - An empty format part is the same as writing none.
Alignment
Alignment is an integer width: positive right-aligns, negative left-aligns; shortfalls are padded with spaces, and overflow is never truncated.
val pi = 3.14159;
print($"right-aligned [{pi,10}] left-aligned [{pi,-10}]");right-aligned [ 3.14159] left-aligned [3.14159 ]Escapes and edge cases
{{and}}output literal braces:$"{{a}}"gives{a}; ther$forms follow the same rule.- String literals and nested parentheses are allowed inside a hole; they do not close the outer string early.
- The colon of a ternary
? :is taken as the format separator; wrap complex expressions in parentheses:$"{(cond ? a : b)}". - Interpolation strings do not span lines; for multiline use
r$#"..."#. - A non-integer literal in the alignment slot is treated as 0.
r$: raw plus interpolation
r$"..." and r$#"..."# combine raw with interpolation: no backslash escapes (\n is the literal two characters), the literal segment can span lines, and holes still fire.
val name = "handbook";
print(r$"no escapes \n stay raw, {name} interpolates");no escapes \n stay raw, handbook interpolates