Introduction
String Interpolation refers to substitution of defined variables or expressions in a given String with respected values. String Interpolation allows users to embed variable references directly in processed string literals. Here’s an example:
val pi = 3.14 println(s"value of pi = $pi") // value of pi = 3.14
And, here’s an example which does not uses any string interpolator.
val pi = 3.14 println("value of pi = "+pi) // value of pi = 3.14
Starting in Scala 2.10.0
, Scala offers a new mechanism to create strings from your data: String Interpolation.
Types of String Interpolator
Scala provides three string interpolation methods out of the box: s
, f
and raw
.
1. s Interpolator
Prepending s
to any string literal allows the usage of variables directly in the string. Within the String, we can access variables, object fields, functions calls, etc. You’ve already seen an example here:
val pi = 3.14 println(s"value of pi = $pi") // value of pi = 3.14
String interpolators can also take arbitrary expressions. For example:
println(s"1 + 1 = ${1 + 1}") // 1 + 1 = 2
Any arbitrary expression can be embedded in ${}
.
For some special characters, it is necessary to escape them when embedded within a string. To represent an actual dollar sign you can double it $$
, like here:
println(s"New offers starting at $$15.00")
which will print the string New offers starting at $15.00
.
Note: The
s
that’s placed before each string literal is actually a method.
2. f Interpolator
Prepending f
to any string literal allows the creation of simple formatted strings, similar to printf
in other languages. When using the f
interpolator, all variable references should be followed by a printf-style format string, like %d
. Let’s look at an example:
val height = 1.9d val name = "James" println(f"$name%s is $height%2.2f meters tall") // James is 1.90 meters tall
The f
interpolator is typesafe. If you try to pass a format string that only works for integers but pass a double, the compiler will issue an error. For example:
val height: Double = 1.9d scala> f"$height%4d" <console>:9: error: type mismatch; found : Double required: Int f"$height%4d" ^
The f
interpolator makes use of the string format utilities available from Java. The formats allowed after the %
character are outlined in the Formatter javadoc. If there is no %
character after a variable definition a formatter of %s
(String) is assumed.
3. raw Interpolator
The raw interpolator is similar to the s
interpolator except that it performs no escaping of literals within the string. Here’s an example processed string:
scala> s"a\nb" res0: String = a b
Here the s
string interpolator replaced the characters \n
with a return character. The raw
interpolator will not do that.
scala> raw"a\nb" res1: String = a\nb
The raw
interpolator is useful when you want to avoid having expressions like \n turn into a return character.
In addition to the three default string interpolators, users can define their own.
Create your own interpolator
If you’re still asking yourself what is this s
before string literal the answer is that processed string literal is a code transformation which compiler transforms into a method call s
on an instance of StringContext
. In other words expression like
s"x is $x"
is rewritten by compiler to
StringContext("x is ", "").s(x)
Let’s create our own string interpolator which will work as s
interpolator with added some debug info to the resulting string:
import java.util.Date import java.text.SimpleDateFormat object Interpolation { implicit class LogInterpolator(val sc: StringContext) extends AnyVal { def log(args: Any*): String = { val timeFormat = new SimpleDateFormat("HH:mm:ss") s"[DEBUG ${timeFormat.format(new Date)}] ${sc.s(args:_*)}" } } val logString = "one plus one is" def demo = log"$logString ${1+1}" }
In the code above implicit classes and extending AnyVal
(so called Value Classes) are also new features in Scala 2.10. Since any interpolator is in fact a method of StringContext
class we can easily use them in our own ones (in the example we use s
method forming the resulting string to not bother with implementing it in our new interpolator). The string interpolation
log"$logString ${1+1}"
will be rewritten by compiler to
new LogInterpolator(new StringContext("", " ", "")).log(logString, 2)
which is a nice combination of new Scala 2.10 features itself.
This new technique is useful writing more readable code, safe and allows to extend and combine existing functionality.
The question that I’ve been pondering lately, is how to use string interpolators and internationalization… ideas?
I haven’t thought of this before but after reading your comment , I dig down and found this :-
https://www.reddit.com/r/scala/comments/31iey4/scala_string_interpolation_why_the_s/
So, interpolators can be used as a powerful tool in I18N. 🙂
I’m not sure that quite does the trick… you’re basically doing a map of strings all within the same source file, that would get ugly very quick if you needed to support many languages, or if you needed to outsource the translation to another group.
I just saw this library: https://github.com/makkarpov/scalingua I’m going to have to take a closer look to see if it accomplishes what I need.
Yaa.. you are correct in all the ways but actually I gave a simple example just for the understanding.