Program Structure

Strings & Templates

Inspect Unicode text by scalar values and select ordinary, multiline, path, regex, shell, or SQL forms.

Use ordinary strings for text your program displays or compares. Use registry-tagged templates when values carry path, regular expression, shell, or SQL intent that requires structured representation. Template values carry structured tag intent alongside their content.

Start with observable Unicode text

Save this as strings-templates.tpz:

TOPAZ
let title = "Topaz 💎"
let scalarCount = title.scalars().length
let configPath = p"config/topaz.toml"
let query = sql"SELECT name FROM projects WHERE title = {title}"

print("{title}: {scalarCount}")

Check and run it:

BASH
topaz check strings-templates.tpz
topaz run strings-templates.tpz

The output is:

Output
Topaz 💎: 7

title contains seven Unicode scalar values: five letters, one space, and one emoji. The scalars() method returns an Array<string> whose elements are single-scalar strings. This provides the standard method to inspect text positions. Storage bytes do not represent string positions, and Topaz performs no implicit Unicode normalization.

Because configPath uses the p template, it carries path-normalization intent. query uses the sql template, where {title} serves as a parameter boundary instead of direct SQL text insertion. The program omits printing both templates because template values are structured, non-renderable entities rather than ordinary display strings.

Choose the form by the value you need

NeedFormBoundary
Display or compare text"Hello, {name}"Interpolation uses the standard value renderer
Multiline text"""..."""Closing-delimiter indentation controls exact stripping
A path templatep"config/app.toml"Carries platform path-normalization intent
A regex templater"^[a-z]+$"Only the specified reduced-escaping floor is portable
Shell command datash"tool {argument}"Construction does not execute a process
Parameterized SQL datasql"WHERE id = {id}"Interpolation becomes parameter metadata

The p, r, sh, and sql tags work with ordinary or triple-quoted strings. The tag must directly precede the opening quote without intervening whitespace. With a space, p "file" parses as an identifier followed by a string rather than a call, producing a parse error.

Ordinary and triple-quoted strings support {expression} interpolation and the fixed escape set. When a newline immediately follows a triple-quoted opening delimiter, that initial newline is omitted. The exact spaces-and-tabs prefix preceding the closing delimiter must appear on each nonblank content line before Topaz removes it.

All tagged templates (p, r, sh, and sql) produce the built-in opaque type template. Use template in binding and return annotations, for example let query: template = sql"..." or function query() -> template { ... }. A template is distinct from string. Its .tag accessor returns the producing tag name as a string, and .parts returns the literal segments between interpolations as an Array<string>.

Common correction

Do not use text[0], text.length, or slicing operations to inspect a string. Call text.scalars() and process the result using standard Array operations. This provides scalar access rather than grapheme-cluster segmentation.

Backticks, ${expression}, single-quoted strings, html"...", unrecognized adjacent tags, and user-defined tags are non-canonical. An sh template does not execute commands, and SQL interpolation does not permit direct text insertion into queries. HTML templates, user tag registration, grapheme-cluster APIs, direct string slicing, a fully fixed cross-platform regex dialect, and shell execution semantics fall outside this language surface.

A template value cannot be used as an ordinary string. Because template is a built-in type name, declarations named record template, enum template, or newtype template are rejected.

Refer to Lexical Structure & Layout for quoting and newline rules, Runtime Behavior for rendering details, and Forbidden & Deferred Forms for familiar syntax options that are intentionally unavailable.