Use an ordinary string for text your program will display or compare. Use a registry-tagged template when the value carries path, regular-expression, shell, or SQL intent that must stay structured. These are different choices: a template value is not merely a string with decorative syntax.
Start with observable Unicode text
Save this as strings-templates.tpz:
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:
topaz check strings-templates.tpz
topaz run strings-templates.tpz
The output is:
Topaz 💎: 7title contains seven Unicode scalar values: five letters, one space, and one
emoji. scalars() returns an Array<string> whose elements are
single-scalar strings. That is the supported way to inspect text positions.
Storage bytes are not string positions, and Topaz performs no implicit Unicode
normalization.
configPath is a p template, so it carries path-normalization intent.
query is a sql template; {title} becomes a parameter boundary rather
than direct SQL text insertion. The program does not print either template
because template values are structured, non-renderable values rather than
ordinary display strings.
Choose the form by the value you need
| Need | Form | Boundary |
|---|---|---|
| Display or compare text | "Hello, {name}" | Interpolation uses the standard value renderer |
| Multiline text | """...""" | Closing-delimiter indentation controls exact stripping |
| A path template | p"config/app.toml" | Carries platform path-normalization intent |
| A regex template | r"^[a-z]+$" | Only the specified reduced-escaping floor is portable |
| Shell command data | sh"tool {argument}" | Construction does not execute a process |
| Parameterized SQL data | sql"WHERE id = {id}" | Interpolation becomes parameter metadata |
All four tags—p, r, sh, and sql—work with ordinary or triple-quoted
strings. The tag must touch the opening quote with no whitespace. With a space,
p "file" is an identifier followed by a string, not a call.
Ordinary and triple-quoted strings use {expression} interpolation and the
fixed escape set. If a triple-quoted opening delimiter is immediately followed
by a newline, that first newline is omitted. The exact spaces-and-tabs prefix
before the closing delimiter must appear on each nonblank content line and is
then removed.
Common correction
Do not write text[0], text.length, or a slice to inspect a string. Use
text.scalars() and then ordinary Array operations. This is scalar access, not
a promise of grapheme-cluster segmentation.
Backticks, ${expression}, single-quoted strings, html"...", unknown
adjacent tags, and user-defined tags are not canonical. An sh template does
not execute, and SQL interpolation does not authorize direct source insertion.
HTML templates, user tag registration, grapheme-cluster APIs, direct string
slicing, a fully fixed cross-platform regex dialect, and shell execution
semantics remain outside this language surface.
See Lexical Structure & Layout for quoting and newline rules, Runtime Behavior for rendering, and Forbidden & Deferred Forms for familiar spellings that are intentionally unavailable.