§9 String Interpolation
let name = "Sailfin";let greeting = "Hello, ${ name }!"; // "Hello, Sailfin!"let math = "2 + 2 = ${ 2 + 2 }"; // "2 + 2 = 4"let nested = "User: ${ user.name.trim() }"; // arbitrary expressions${ expr } opens an interpolation. Whitespace at the edges is insignificant:
${name} and ${ name } are equivalent. A bare $ not followed by { is
literal ("Total: $5"). Nested braces inside the expression are matched by
depth, so "${ f({a: 1}) }" parses as a single interpolation. The compiler
lowers interpolated strings into segment arrays evaluated at runtime.
The older {{ expr }} form is deprecated but still accepted during a
migration window; using it emits a non-fatal W0212 deprecation warning at
sfn check time. It will be removed in a later phase.
A literal-${ escape (\${) is not yet available — it is deferred to a
follow-up (SFEP-0057 Phase 4 / SFN-483) — so a string that needs a literal
${ should currently be assembled another way (e.g. concatenation) rather
than relying on an escape.
Primitive optional unions such as int | null render the active non-null
payload in direct, flow-narrowed, and match-bound positions.
Concatenating a numeric or boolean operand (+)
Section titled “Concatenating a numeric or boolean operand (+)”string + <int | float | bool> (either operand order) concatenates by
stringifying the non-string operand, rather than requiring an explicit cast:
let n = 42;let f = 1.5;let t = true;
let a = "n=" + n; // "n=42"let b = "f=" + f; // "f=1.5"let c = "t=" + t; // "t=1"let d = n + " items"; // "42 items" -- works with the string on either sideThis is defined as sugar for string + (x as string) — the same
number.to_string lowering the as string cast uses — so the two can never
diverge. Booleans render "1"/"0", not "true"/"false", matching the
as string cast rather than string interpolation’s "true"/"false"
rendering (see above). This is easy to get wrong when porting code from
interpolation to concatenation — check for it explicitly.
Indexing a string still yields a single-character string (s[i]), not a
numeric code point, so concatenating an indexed character ("c=" + s[1])
is unaffected and continues to concatenate the character itself.
Raw pointer arithmetic (*u8 + int) is a distinct operation and is not
concatenation — it still lowers to pointer offsetting, never stringification.