How do I escape characters in EK9 string interpolation?
← Getting Started · Ref: Q43
EK9 has two string types with different escaping rules. Double-quoted strings are plain text where $ is just a regular character. Backtick strings support interpolation where ${...} evaluates expressions. This means backtick strings need special escaping for $ and backtick characters that double-quoted strings do not.
BACKTICK STRING ESCAPING (interpolation strings)
Backtick strings evaluate ${...} expressions. To include literal special characters:
\$ Literal dollar sign (prevents interpolation trigger) \` Literal backtick character \t Tab
Newline \\ Literal backslash \uXXXX Unicode code point
Examples:
salary <- 42000 stdout.println(`Your salary is \$${salary}`) //Output: Your salary is $42000
stdout.println(`Use \`backticks\` for interpolation`) //Output: Use `backticks` for interpolation
DOUBLE-QUOTED STRING ESCAPING (plain text)
Double-quoted strings have NO interpolation, so $ is just a regular character:
plainDollar <- "Price: $42" //Output: Price: $42
withQuote <- "She said \"hello\"" //Output: She said "hello"
withBackslash <- "C:\\Users\\file.txt" //Output: C:\Users\file.txt
THE CHARACTERS ${ THEMSELVES
A double-quoted string cannot hold ${ at all: it would never be interpolated, so the compiler rejects it (E07901) and the error spells out both backtick rewrites - one that interpolates, one that keeps the characters. A backslash is not an escape for $ in a double-quoted string ("\${name}" keeps the backslash).
To keep the characters ${ as text, write them in a backtick string with the dollar escaped:
stdout.println(`Write \${name} to interpolate a variable`) //Output: Write ${name} to interpolate a variable
The everyday case is a regular expression replacement that names a group - it needs the characters ${day}, not a variable:
dueLine.replace(namedDate, `\${day}.\${month}.\${year}`)
WHY THIS MATTERS FOR EK9 OPERATORS
EK9 uses $ in three operator contexts:
$value to-string conversion
$$record to-JSON serialization
$?.path data navigation path literal
When you want to MENTION these operators as text in an interpolated string, you must escape the dollar sign:
name <- "EK9" stringRep <- $name stdout.println(`\$ converts to string: ${stringRep}`)
me <- PersonDetail(name: "Steve", age: 30) jsonRep <- $$me stdout.println(`\$\$ converts to JSON: ${jsonRep}`)
navPath <- $?.store.book[0].title stdout.println(`\$? creates a path: ${navPath}`)
Without the backslash, the lexer would try to parse $$ or $? as operators inside the string, causing parse errors.
USING OPERATORS DIRECTLY INSIDE INTERPOLATION
You can use $ and $$ operators directly inside ${...} without an intermediate variable:
stdout.println(`Direct JSON: ${$$me}`) stdout.println(`Direct to-string: ${$salary}`)
The ${$$me} pattern evaluates $$me (to-JSON) and interpolates the result. The ${$salary} pattern evaluates $salary (to-string) and interpolates. This is concise and avoids creating temporary variables just for display.
COMBINING ESCAPED AND INTERPOLATED CONTENT
You can mix escaped dollar signs and interpolation in the same string:
price <- 9.99 stdout.println(`Item costs \$${price} (tax not included)`) //Output: Item costs $9.99 (tax not included)
The \$ produces a literal dollar sign, then ${price} is the interpolation expression. The lexer processes them left to right: backslash-dollar is a literal, dollar-brace is interpolation.
BACKSLASH-SPACE SHORTCUT
If a backslash is followed by a space, it is treated as just a backslash. This is a convenient alternative to \\ when the backslash is not immediately before a special character:
withBs <- "path\ here" //Output: path\ here
QUICK REFERENCE TABLE
Escape Double-quoted Backtick
${ E07901 error starts interpolation
\$ not an escape REQUIRED (prevents interpolation)
\` not needed REQUIRED (prevents string end)
\" REQUIRED not needed
\t tab tab
newline newline
\\ backslash backslash
\uXXXX unicode unicode
The key insight: double-quoted strings need \" for quotes, backtick strings need \$ for dollars and \` for backticks. Each string type only needs escaping for its own delimiter and trigger characters. And ${ belongs only in a backtick string - in a double-quoted one it is a compile error (E07901).
See Q37 (How do I work with strings in EK9?) for string methods, streaming, and interpolation basics. See Q42 (How does the Path type work?) for the $? operator that often needs escaping in interpolated output. See Q113 for the text construct for internationalization.
Use 'ek9 -h String' to see the full String API. See Q188 for JSON as first-class type and the $$ operator. See Q242 for conversion operators ($, $$, #?) used in interpolation.
Example
defines module qa.escape.interpolation defines record PersonDetail name <- String() age <- Integer() default PersonDetail() PersonDetail() -> name as String age as Integer this.name :=: name this.age :=: age default operator $$ default operator ? defines program EscapingDemo() stdout <- Stdout() // === BACKTICK-SPECIFIC ESCAPING === // \$ produces a literal dollar sign in backtick strings salary <- 42000 stdout.println(`Your salary is \$${salary}`) // Show the $ operator label without triggering interpolation name <- "EK9" stringRep <- $name stdout.println(`\$ converts to string: ${stringRep}`) // Show the $$ operator label me <- PersonDetail(name: "Steve", age: 30) jsonRep <- $$me stdout.println(`\$\$ converts to JSON: ${jsonRep}`) // Show the $? path literal label navPath <- $?.store.book[0].title stdout.println(`\$? creates a path: ${navPath}`) // \` produces a literal backtick inside a backtick string stdout.println(`Use \`backticks\` for interpolation`) // \${ keeps the characters ${ as text - a double-quoted String cannot hold them (E07901) stdout.println(`Write \${name} to interpolate a variable`) // === DOUBLE-QUOTED STRING ESCAPING === // In double-quoted strings, $ is just a regular character plainDollar <- "Price: $42" stdout.println(plainDollar) // \" for literal quote in double-quoted strings withQuote <- "She said \"hello\"" stdout.println(withQuote) // \\ for literal backslash withBackslash <- "C:\\Users\\file.txt" stdout.println(withBackslash) // === COMMON ESCAPE SEQUENCES (both string types) === // \t tab, \n newline withTab <- `Column1\tColumn2` stdout.println(withTab) withNewline <- "Line1\nLine2" stdout.println(withNewline) // \uXXXX for Unicode code points copyright <- "\u00A9 2024" stdout.println(copyright) // Backslash followed by space is just a backslash withBs <- "path\ here" stdout.println(withBs) // === OPERATORS DIRECTLY IN INTERPOLATION === // Use $$ directly inside ${...} — no intermediate variable needed stdout.println(`Direct JSON: ${$$me}`) // Use $ directly inside ${...} stdout.println(`Direct to-string: ${$salary}`) // === COMBINING ESCAPING WITH INTERPOLATION === // Mix escaped dollar signs and interpolation in the same string price <- 9.99 stdout.println(`Item costs \$${price} (tax not included)`) // Multiple interpolations with escaped operators x <- 42 stdout.println(`Integer ${x}, use \$ for to-string, \$\$ for to-JSON`)
Common mistakes
E08180 — Record fields must be initialised at declaration. Declaring fields without initialisation triggers E08180. Use inline initialisation like 'String()' to create an unset-but-initialised field. See ek9 -h E08180 for details.
Incorrect:
name as String age as Integer
Correct:
name <- String() age <- Integer()
E07901 — A double-quoted String cannot hold ${ - it never interpolates, so the compiler rejects it (E07901) rather than print it. For the characters themselves write \${ in a backtick String; a backslash is not an escape for $ in a double-quoted String. See ek9 -h E07901 for details.
Incorrect:
stdout.println("Write ${name} to interpolate a variable")
Correct:
stdout.println(`Write \${name} to interpolate a variable`)
Other ways to ask this
- How do I include a literal dollar sign in a backtick string in EK9?
- What is the difference between escaping in double-quoted and backtick strings in EK9?
- How do I display the $ and $$ operators as text in interpolated strings in EK9?
- Why does my backtick string fail when I use $ without interpolation in EK9?
- How do I write a literal ${ in an EK9 string?
- Why is "${name}" in double quotes a compile error in EK9?
Coming from another language?
Java: no string interpolation until Java 21 string templates (preview), $ is a regular character in all strings, escape sequences same as EK9 double-quoted strings. Python: f-strings use {expr} for interpolation, literal brace needs {{ doubling not backslash escaping, $ is a regular character. JavaScript: template literals use ${expr} in backticks, literal backtick needs backslash escaping, literal dollar-brace needs \${ or ${'$'}, very similar rules to EK9 backtick strings. Kotlin: string templates use $var and ${expr}, literal dollar needs ${'$'} trick (no backslash escape), a common pain point. Ruby: string interpolation uses #{expr} in double-quoted strings, $ is a regular character but #{ needs escaping. C#: interpolated strings use $"...{expr}..." and literal brace needs {{ doubling. EK9: backtick strings use ${expr}, \$ for literal dollar, \` for literal backtick, double-quoted strings are plain text where $ needs no escaping. The backslash-dollar approach is more intuitive than Python's brace doubling or Kotlin's ${'$'} workaround. Kotlin, Groovy, Dart, PHP and the shells interpolate DOUBLE quotes, so "${name}" is the habit to unlearn: in EK9 it is a compile error (E07901), never silently the characters.
Keywords: operator, start, dollar, backtick, backslash, intro, escape, beginner, quote, unicode, first, string, literal, interpolation