Strings
Tova provides two kinds of string literals and a rich set of built-in methods and standalone functions for working with text.
String Literals
Double-Quoted Strings (Interpolation)
Double-quoted strings support interpolation with {expr}:
name = "Alice"
greeting = "Hello, {name}!" // "Hello, Alice!"
math = "1 + 2 = {1 + 2}" // "1 + 2 = 3"
info = "User {name} has {len(items)} items"Any valid expression can appear inside the braces:
result = "The answer is {if x > 0 { "positive" } else { "non-positive" }}"
list = "Items: {items.join(", ")}"Single-Quoted Strings (No Interpolation)
Single-quoted strings are literal -- no interpolation is performed:
pattern = 'no {interpolation} here' // literal: no {interpolation} here
regex = '\d+\.\d+'Triple-Quoted Strings (Multiline)
Triple-quoted strings """...""" span multiple lines and support interpolation. Indentation is auto-dedented based on the closing """:
message = """
Hello, {name}!
Welcome to Tova.
Today is {date}.
"""
// Leading whitespace is stripped based on closing """ indentationTriple-quoted strings are ideal for multi-line text blocks, templates, and embedded content.
Raw Strings
Prefix a string with r to disable escape sequence processing:
path = r"C:\Users\Alice\Documents" // backslashes are literal
regex_str = r"\d+\.\d+" // no need to double-escapeRaw strings are useful for file paths, regex patterns, and any text where backslashes should remain literal.
F-Strings
Prefix a string with f to explicitly mark it as interpolated:
name = "Alice"
greeting = f"Hello, {name}!" // "Hello, Alice!"F-strings are semantically identical to regular double-quoted strings. The f prefix is optional and serves as a visual marker that interpolation is used.
Regex Literals
Tova supports regex literals using /pattern/flags syntax:
pattern = /\d+/g
email_re = /^[\w.]+@[\w.]+\.\w+$/i
// Available flags: g (global), i (case-insensitive), m (multiline),
// s (dotAll), u (unicode), y (sticky)Regex literals compile to JavaScript RegExp objects and work with the regex stdlib functions:
if regex_test("hello123", /\d+/) {
print("Contains digits")
}
matches = regex_find_all("a1b2c3", /\d/)Escape Sequences
Both string types support the following escape sequences:
| Sequence | Meaning |
|---|---|
\n | Newline |
\t | Tab |
\r | Carriage return |
\\ | Backslash |
\" | Double quote |
\' | Single quote |
\{ | Literal { (prevents interpolation in double-quoted strings) |
multiline = "Line one\nLine two\nLine three"
path = "C:\\Users\\Alice\\Documents"
quoted = "She said \"hello\""
literal_brace = "Use \{braces} for interpolation"String Multiplication
Repeat a string by multiplying it with an integer:
separator = "-" * 40
// "----------------------------------------"
border = "=" * 60
indent = " " * 4
dots = "." * 20This is useful for formatting output:
fn print_header(title) {
line = "=" * len(title)
print(line)
print(title)
print(line)
}
print_header("Report")
// ======
// Report
// ======Method-Style String Functions
Tova provides string manipulation through method calls on string values:
Case Conversion
text = "hello world"
text.upper() // "HELLO WORLD"
text.lower() // "hello world"
text.capitalize() // "Hello world"
text.title_case() // "Hello World"Converting between naming conventions:
name = "myVariableName"
name.snake_case() // "my_variable_name"
name2 = "my_variable_name"
name2.camel_case() // "myVariableName"Searching and Testing
text = "Hello, World!"
text.contains("World") // true
text.starts_with("Hello") // true
text.ends_with("!") // true
text.contains("xyz") // falseSplitting into Parts
text = "Hello, World!"
text.chars() // ["H", "e", "l", "l", "o", ",", " ", "W", "o", "r", "l", "d", "!"]
text.words() // ["Hello,", "World!"]
text.lines() // ["Hello, World!"]
multiline = "Line 1\nLine 2\nLine 3"
multiline.lines() // ["Line 1", "Line 2", "Line 3"]Standalone String Functions
Tova also provides standalone functions that take a string as their first argument. These work well with the pipe operator:
Trimming and Manipulating
padded = " hello "
trim(padded) // "hello"
text = "hello world"
replace(text, "world", "Tova") // "hello Tova"
repeat("ha", 3) // "hahaha"Splitting and Joining
csv = "alice,bob,carol"
split(csv, ",") // ["alice", "bob", "carol"]
names = ["Alice", "Bob", "Carol"]
join(names, ", ") // "Alice, Bob, Carol"
join(names, " and ") // "Alice and Bob and Carol"Case Conversion (Standalone)
upper("hello") // "HELLO"
lower("HELLO") // "hello"
capitalize("hello") // "Hello"
title_case("hello world") // "Hello World"
snake_case("helloWorld") // "hello_world"
camel_case("hello_world") // "helloWorld"Searching (Standalone)
contains("hello world", "world") // true
starts_with("hello", "hel") // true
ends_with("hello", "llo") // trueSplitting into Parts (Standalone)
chars("hello") // ["h", "e", "l", "l", "o"]
words("hello world") // ["hello", "world"]
lines("a\nb\nc") // ["a", "b", "c"]Using Strings with Pipes
The standalone functions are designed to work smoothly with the pipe operator |>:
result = " Hello, World! "
|> trim()
|> lower()
|> replace("world", "tova")
|> capitalize()
// "Hello, tova!"csv_line = " Alice , Bob , Carol "
names = csv_line
|> trim()
|> split(",")
|> map(fn(s) trim(s))
// ["Alice", "Bob", "Carol"]String Concatenation
Use string interpolation or the + operator:
first = "Hello"
second = "World"
// Interpolation (preferred)
greeting = "{first}, {second}!"
// Plus operator (works since strings support +)
greeting = first + ", " + second + "!"The ++ operator is available in match patterns only for string prefix matching:
match path {
"/api/" ++ rest => handle_api(rest)
"/static/" ++ file => serve_static(file)
_ => not_found()
}TIP
Prefer string interpolation over concatenation. "Hello, {name}!" is clearer and less error-prone than "Hello, " + name + "!".
Practical Tips
Choose the right quote style. Use double quotes "..." when you need interpolation, and single quotes '...' for literal strings (regex patterns, templates where braces should not be interpreted).
Use method-style calls for chaining on a known string:
input.trim().lower().replace(" ", "_")Use standalone functions with pipes for data pipelines:
data |> trim() |> split(",") |> map(fn(s) s.upper())String multiplication is great for formatting:
fn table_row(label, value) {
padding = " " * (20 - len(label))
"{label}{padding}{value}"
}
print(table_row("Name", "Alice"))
print(table_row("Age", "30"))
// Name Alice
// Age 30