Loft strings can embed expressions inside {...} braces. A colon after the expression introduces a format specifier that controls width, alignment, precision, number base, and output style.
Basic interpolation
Any expression inside {...} is evaluated and converted to text.
fn main() {
name = "world";
assert("hello {name}" == "hello world", "basic interpolation");
assert("1 + 2 = {1 + 2}" == "1 + 2 = 3", "expression in braces");
Width and alignment
A number after : sets the minimum width. The value is padded with spaces to fill the width. {val:6} — right-aligned (default for numbers) {val:>6} — right-aligned (explicit) {val:<6} — left-aligned {val:^6} — centered For text, the default alignment is left. For numbers, right.
assert("{42:6}" == " 42", "default number align is right");
assert("{42:>6}" == " 42", "explicit right-align");
assert("{42:<6}" == "42 ", "left-align number");
assert("{42:^6}" == " 42 ", "center-align number");
s = "hi";
assert("{s:6}" == "hi ", "default text align is left");
assert("{s:>6}" == " hi", "right-align text");
assert("{s:^6}" == " hi ", "center-align text");
Zero padding
Prefix the width with 0 to pad with zeros instead of spaces.
assert("{7:03}" == "007", "zero-padded 3 digits");
assert("{42:05}" == "00042", "zero-padded 5 digits");
assert("{-1:04}" == "-001", "zero-padded negative: sign before zeros");
Signed format
+ forces a sign on positive numbers.
assert("{42:+}" == "+42", "explicit positive sign");
assert("{-42:+}" == "-42", "negative sign always shown");
assert("{0:+}" == "+0", "sign on zero");
Hexadecimal, binary, octal
:x for lowercase hex, :#x for hex with 0x prefix. :b for binary, :o for octal.
assert("{255:x}" == "ff", "hex lowercase");
assert("{255:#x}" == "0xff", "hex with prefix");
assert("{10:b}" == "1010", "binary");
assert("{8:o}" == "10", "octal");
Float precision
.N after the colon limits decimal places.
assert("{3.125:.1}" == "3.1", "1 decimal place");
assert("{3.125:.2}" == "3.12", "2 decimal places");
assert("{3.125:.0}" == "3", "0 decimal places");
assert("{0.0:.3}" == "0.000", "trailing zeros");
Width + precision
Combine width and precision: {val:W.P} where W is total width and P is decimal places.
assert("{3.125:8.2}" == " 3.12", "width 8 precision 2");
assert("{-3.125:8.2}" == " -3.12", "negative width+precision");
JSON format
:j serialises a struct or value as JSON. :j serialises a struct as JSON. Use it on struct values, not primitives. See the JSON documentation page for full details.
Vector format
Vectors are formatted as [a,b,c] by default. A format specifier inside a for loop applies to each element.
v = [1, 2, 3];
assert("{v}" == "[1,2,3]", "default vector format");
assert("{for fmt_n in 1..4 {fmt_n * 10}:04}" == "[0010,0020,0030]", "formatted vector elements");
Long and single types
Long integers and single-precision floats use the same format specifiers.
n = 1000000l;
assert("{n}" == "1000000", "long default");
assert("{n:>10}" == " 1000000", "long right-aligned");
f = 1.5f;
assert("{f}" == "1.5", "single default");
Character format
c = 'A';
assert("{c}" == "A", "character default");
Boolean format
assert("{true}" == "true", "boolean true");
assert("{false}" == "false", "boolean false");
}