Scala Tutorials Part #11 - String Interpolation


String Interpolation

In this part we are going to see a pretty nifty feature of scala called String interpolation.

This is part 11 of the scala tutorial series. Check here for the full series.

Index

String concatenation in java

There is no string interpolation/string variable substitution in java so to speak. Seasoned java programmers are used to string concatenation.

public class JavaRunner {

    public static void main(String[] args) {

       String name = "John";
       String weight = "154";
       String unit = "Pounds";

       System.out.println(name + " weighs " + weight + " " + unit);

    }
}

This works as intended so what is so special with interpolation? Read on to find out more.

Concatenation vs Interpolation

Let’s see how we do the same thing with string interpolation.

  val name = "John"
  val weight = 154
  val unit = "Pounds"

  //String concatenation
  println(name + " weighs " + weight + " " + unit)

  //Interpolation
  println(s"$name weighs $weight $unit")

Both the versions produce the same result, but the interpolation seems to be slightly better in terms of syntax when compared with concatenation.

Also there are lesser chances to make mistakes in the interpolated version.

Anatomy of a string interpolator in scala

The syntax that we encountered might be weird in the beginning but the s"" before the string is actually a method in StringContext.scala.

It goes as follows,

def s(args: Any*): String = standardInterpolator(treatEscapes, args)

which then again calls another method called standardInterpolator.

In scala there are three string interpolators,

We will look at the other ones in sections below.

If we follow the code path, it ends up in the method called standardInterpolator which does a couple of steps to transform the given result into a complete string. One important point to note is that the entire process uses a StringBuilder underneath.

This is different in terms of performance with the traditional string concatenation which in the above example creates additional 3 strings including the space string. Of course we can code that string using a StringBuilder but the syntactic sugar is pretty nice.

The $ symbol is used to differentiate variables and strings.

Combining operations with standard interpolation

We can combine arithmetic operations with interpolation as follows.

  val name = "John"
  val weight = 154
  val unit = "Pounds"

  val name2 = "Jack"
  val weight2 = 166


  println(s"$name2 weighs ${weight2 - weight} $unit more than $name ")

The operation needs to be inside ${} to work correctly, otherwise it would replace the variables but will not perform the minus operation. For example,

println(s"$name2 weighs $weight2-$weight $unit more than $name ")

would just print Jack weighs 166-154 Pounds more than John, so the ${} is important.

Any arbitrary expression can be embedded inside ${} and it would just work.

Another thing to note is that string interpolation is typesafe, you can’t just include variables that don’t exist or perform any syntax errors inside of ${}.

Format interpolator

The format interpolator is similar to the printf command in the C language.

  val height = 1.9d
  val name = "James Sawyer"
  println(f"$name%s is $height%2.2f meters tall")

Here instead of s"" we use f"" as the prefix.

In the given example %s is used to denote a string and %f to denote double.

The 2.2f is used to denote precision i.e 2 decimals before the point and 2 after the point.

If our need is just printing to the console we can just use the printf method.

  val height = 1.9d
  val name = "James Sawyer"

  //The format interpolator. Produces a string as an output
  println(f"$name%s is $height%2.2f meters tall")

  //C Style abstraction over java PrintStream
  printf("%s is %2.2f meters tall",name,height)

But in many cases we would want to use the formatted value as a string elsewhere. A good example is printing out values in logs. Without string interpolation we would have to rely on the logging library or use string concatenation.

Note that the f interpolator is type safe i.e something like below will throw an error.

f interpolator error

Raw interpolator

The raw interpolator is pretty similar to the standard one, except that literals are not escaped within the string.

  val height = 1.9d

  val name = "James Sawyer"

  //Tab is printed after $name is
  println(s"$name is \t $height meters tall")

  // \t is just printed as a string
  println(raw"$name is \t $height meters tall")

It was not named just r"" cause that would cause confusion with regular expressions.

This is useful when we dont want to escape literals.

One can also use the standard interpolator and ignore literals as below,

println(s"$name is \\t $height meters tall")

It is a design decision that the developer can take. If there are only a handful of literals to be ignored then we can hard code them or else use the raw interpolator.

We can also write our own interpolator, but that is kind of advanced and not needed in most of the cases.

Type annotation in interpolators

We can annotate the types for the variables we put inside the interpolator and it will throw an error during compile time.

Type annotation in interpolation

In the above example, the second element in the list or any element in that matter is of Any type and not of the String type.

Interpolation in other languages

As mentioned in the string intepolation wiki, this concept of embedding variable references is not new to scala.

In fact very early languages such as bash and perl had this functionality.

This is a pretty neat feature considering that Scala was aimed to used for everything including scripting.

We will look at how to use scala for scripting in future articles.

Interpolation is commonly used across many frameworks/libraries in scala. In fact it is considered a de-facto standard instead of string concatenation.

On the whole this might not seem as a pretty big thing when compared to Java string concatenation, but it is small things like these that transform the entire language into a better one.

Stay tuned


Tagged Under


Scala


Search this website...




Keeping up with blogs...

I blog occasionally and mostly write about Software engineering and the likes. If you are interested in keeping up with new blog posts, you should follow me on twitter where I usually tweet when I publish them. You can also use the RSS feed , or even subscribe via email below.

Feedio Subscribe


Share & Like

If you like this post, then you can either share/discuss/vote up on the below sites.



Thoughts ...

Please feel free to share your comments below for discussion

Blog comments powered by Disqus