String Formatting

The & operator can be used for simple string concatenation:

let msg = "hello" & "world"

The strutils module provides string interpolation from a format string using the % operator.

import std/strutils

# numbered arguments
echo "$1 $2" % ["hello", "world"]
# you can fetch the next argument using #
echo "$# $#" % ["hello", "world"]
# can support named arguments
echo "$first $second" % ["first", "hello", "second", "world"]

Alternatively, you can use the functionality provided by the strformat module.

import std/strformat

let
  h = "hello"
  w = "world"

echo fmt"{h} {w}"
echo &"{h} {w}"

The fmt and & operators have a slight difference in usuage: namely, the fmt operator results in a raw string literal which does not interpret escape sequences. Using the & operator is the simplest way around this; other options are listed in the docs.

Non-string arguments

We have seen 3 different string formatting options above. How do you format non-string built-in types?

import std/strutils, std/strformat

let 
  num = 42

# does not work
echo "hello" & num
# this does not work either
echo "hello $1" % [num]
# this works fine
echo &"hello {num}"

# use the $ operator to convert to string
assert $num == "42"

# these work now
echo "hello" & $num
echo "hello $1" % [$num]

That is, the first two methods expect string arguments, the third works with any types. Refer to the docs for format specifiers for alignments, integer and floating presentation types.

Formatting object types

The $ operator is Nim’s version of the string or toString function. You can create string representations for object types as shown below.

import std/strutils, std/strformat

type Fruit = object
  name: string
  color: string
  
proc `$`(self: Fruit): string =
  &"Fruit({self.name}, {self.color})"
  
let apple = Fruit(name: "apple", color: "red")
  
echo apple  # Fruit("apple", "red")
echo $apple # Fruit("apple", "red")

echo "hello " & apple # does not work, like before
echo "hello " & $apple # hello Fruit("apple", "red")

echo "hello $1" % [apple] # does not work, like before
echo "hello $1" % [$apple] # hello Fruit("apple", "red")

# note the difference here
echo &"hello {apple}" # hello (name: "apple", color: "red")
echo &"hello {$apple}" # hello Fruit("apple", "red")

Note that the first line in the last section formats object types (and other types) using an in-built representation and you need to use the $ operator—as in the second line of the last section—if you want to coerce it to a format of your choosing.