String interpolation in Scala 2 (String variable substitution)

Scala string FAQ: How do I embed variables in strings in Scala?

A lot of nice new features were added to the Scala language in version 2.10, but a simple feature that makes me happy is string interpolation. This lets Scala developers embed variables inside strings just like you can do in other languages like Perl, PHP, and Ruby — but in an even more powerful way.

Basic solution

To use basic string interpolation in Scala, precede your string with the letter s and include your variables inside the string, with each variable name preceded by a $ character.

This is shown in the println statement in the following example:

scala> val name = "Fred"
name: String = Fred

scala> val age = 33
age: Int = 33

scala> val weight = 200.00
weight: Double = 200.0

scala> println(s"$name is $age years old, and weighs $weight pounds.")
Fred is 33 years old, and weighs 200.0 pounds.

According to the official Scala string interpolation documentation, when you precede your string with the letter s, you’re creating a processed string literal. This example uses the “s string interpolator,” which lets you embed variables inside a string, where they’re replaced by their values. As stated in the documentation, “Prepending s to any string literal allows the usage of variables directly in the string.”

Using expressions in Scala string literals

In addition to putting variables inside strings, you can include expressions inside a string by placing the expression inside curly braces. According to the official string interpolation documentation, “Any arbitrary expression can be embedded in ${}.”

In the following example, the value 1 is added to the variable age inside the string:

scala> println(s"Age next year: ${age + 1}")
Age next year: 34

This example shows that you can use an equality expression inside the curly braces:

scala> println(s"You are 33 years old: ${age == 33}")
You are 33 years old: true

You’ll also need to use curly braces when printing object fields. The following example shows the correct approach:

scala> case class Student(name: String, score: Int)
defined class Student

scala> val hannah = Student("Hannah", 95)
hannah: Student = Student(Hannah,95)

scala> println(s"${hannah.name} has a score of ${hannah.score}")
Hannah has a score of 95

Attempting to print the values of the object fields without wrapping them in curly braces results in the wrong information being printed out:

// error: this is intentionally wrong
scala> println(s"$hannah.name has a score of $hannah.score")
Student(Hannah,95).name has a score of Student(Hannah,95).score

Because $hannah.name wasn’t wrapped in curly braces, the wrong information was printed; in this case, the toString output of the hannah variable.

‘s’ is a method

The s that’s placed before each string literal is actually a method. Though this seems slightly less convenient than just putting variables inside of strings, there are at least two benefits to this approach:

  • Scala provides other off-the-shelf interpolation functions to give you more power.
  • You can define your own string interpolation functions.

To see why this is a good thing, let’s look at another string interpolation function.

The ‘f’ string interpolator (printf formatting)

In the example in the Solution, the weight was printed as 200.0. This is okay, but what can you do if you want to add more decimal places to the weight, or remove them entirely?

This simple desire leads to the “f string interpolator,” which lets you use printf style formatting specifiers inside strings. The following examples show how to print the weight, first with two decimal places:

scala> println(f"$name is $age years old, and weighs $weight%.2f pounds.")
Fred is 33 years old, and weighs 200.00 pounds.

and then with no decimal places:

scala> println(f"$name is $age years old, and weighs $weight%.0f pounds.")
Fred is 33 years old, and weighs 200 pounds.

As demonstrated, to use this approach, just follow these steps:

  1. Precede your string with the letter f.
  2. Use printf style formatting specifiers immediately after your variables.

The most common printf format specifiers are shown in the table in the Discussion.

Though these examples used the println method, it’s important to note that you can use string interpolation in other ways. For instance, you can assign the result of a variable substitution to a new variable, similar to calling sprintf in other languages:

scala> val out = f"$name, you weigh $weight%.0f pounds."
out: String = Fred, you weigh 200 pounds.

The ‘raw’ interpolator

In addition to the s and f string interpolators, Scala 2.10 includes another interpolator named raw. The raw interpolator “performs no escaping of literals within the string.”

The following example shows how raw compares to the s interpolator:

scala> s"foo\nbar"
res0: String =
foo
bar

scala> raw"foo\nbar"
res1: String = foo\nbar

The raw interpolator is useful when you want to avoid having a sequence of characters like \n turn into a newline character.

Create your own interpolator

In addition to the s, f, and raw interpolators that are built into Scala 2.10, you can define your own interpolators. See the official Scala String Interpolation documentation for an example of how to create your own interpolator.

Note: String interpolation does not work with pattern-matching statements in Scala 2.10. This feature is planned for inclusion in Scala 2.11.

Discussion

Prior to version 2.10, Scala didn’t include the string interpolation functionality just described. If you need to use a release prior to Scala 2.10 for some reason, the solution is to call the format method on a string, as shown in the following examples:

scala> val name = "Fred"
name: java.lang.String = Fred

scala> val age = 33
age: Int = 33

scala> val s = "%s is %d years old".format(name, age)
s: String = Fred is 33 years old

scala> println("%s is %d years old".format(name, age))
Fred is 33 years old

Just as with the string interpolation capability shown in the Solution, you can use this approach anywhere you want to format a string, such as a toString method:

override def toString: String = "%s %s, age %d".format(firstName, lastName, age)

With either of these approaches, you can format your variables using all the usual printf specifiers. The most common format specifiers are shown here:

Format specifier   Description
----------------   ---------------------------------
      %c           Character
      %d           Decimal number (integer, base 10)
      %e           Exponential floating-point number
      %f           Floating-point number
      %i           Integer (base 10)
      %o           Octal number (base 8)
      %s           A string of characters
      %u           Unsigned decimal (integer) number
      %x           Hexadecimal number (base 16)
      %%           Print a “percent” character
      \%           Print a “percent” character

See Also