Strings & Text
String Basics
A string stores bytes and knows its own length. Indices run from 0 to len - 1, and the ^ prefix counts from the end so you rarely need to compute that arithmetic yourself.
Indexing and Iteration
let word = "nim"
echo word.len # 3 — a stored length, not a scan for a terminator
echo word[0] # n — indexing yields a char
echo word[^1] # m — '^1' is the last byte, no off-by-one arithmetic
for ch in word: # iterate bytes directly
echo ch, "=", ord(ch) # n=110 i=105 m=109
# Slices copy, so the original is untouched and immutable when declared 'let'.
echo word[0 .. 1] # ni
var mutable = "abc"
mutable[0] = 'A' # strings are mutable when the binding allows it
echo mutable # Abc
Bytes Versus Characters
Non-ASCII text occupies several bytes per character. When a length must count characters rather than bytes, use the Unicode helpers instead of len.
import std/unicode
let greek = "αβγ"
echo greek.len # 6 — bytes, because each Greek letter is 2 bytes
echo greek.runeLen # 3 — characters
for rune in greek.runes: # iterate characters, not bytes
echo rune # α β γ, one per line
echo greek.toUpperAscii() # ASCII-only case rules: non-ASCII stays as is
Manipulation with strutils
std/strutils holds the everyday text operations. Most of them return a new string; a few mutate in place, and the names make the difference explicit.
Split, Join and Trim
import std/strutils
let csv = " ada , grace , linus "
let fields = csv.split(',') # seq[string]; whitespace is NOT removed
echo fields.len, " fields" # 3
var cleaned: seq[string]
for field in fields:
cleaned.add(field.strip()) # strip removes surrounding whitespace
echo cleaned.join("|") # ada|grace|linus
echo "Hello".toUpperAscii(), " ", "Hello".toLowerAscii() # HELLO hello
echo "report.txt".startsWith("report"), " ", "report.txt".endsWith(".txt")
echo "a,b,,c".count(',') # 3 — count occurrences of a substring
Building and Formatting Text
Text is assembled with concatenation when there are two or three parts, and with interpolation or joins when there are more. Casting any value to text goes through the $ operator.
Concatenation, Repetition, Padding
import std/strutils
echo "log" & "-" & "file" # log-file — '&' joins two strings
echo "ab".repeat(3) # ababab
var line = "item"
line.add(": 3") # 'add' appends in place, avoiding a new string
line.add('!') # chars append too
echo line # item: 3!
# Padding and alignment matter when printing columns.
echo "id".alignLeft(6, '.') & "name" # id....name
echo align("42", 5, '0') # 00042 — right-aligned, zero filled
echo 3.14159.formatFloat(ffDecimal, 2) # 3.14 — fixed decimals
echo $12 & " as text" # '$' converts any value to text
Interpolation with strformat
std/strformat turns a string literal into a template with typed placeholders. It is checked at compile time, so a misspelled name is an error, not an empty field at runtime.
import std/strformat
let user = "ada"
let attempts = 3
let ratio = 0.875
echo &"user={user} attempts={attempts}" # user=ada attempts=3
echo &"success {ratio * 100:.1f}%" # 87.5% — float with one decimal
echo &"{attempts:>4}|" # ' 3|' — width 4, right aligned
echo &"{user:^9}|" # ' ada |' — centered in width 9
# A format string can be stored and reused; the fields are resolved when used.
const template = "attempt {attempts} for {user}"
echo &template