Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

String interpolation in Scala 2.10 - How to interpolate a String variable?

String interpolation is available in Scala starting Scala 2.10

This is the basic example

 val name = "World"            //> name  : String = World  val message = s"Hello $name"  //> message  : String = Hello World 

I was wondering if there is a way to do dynamic interpolation, e.g. the following (doesn't compile, just for illustration purposes)

 val name = "World"            //> name  : String = World  val template = "Hello $name"  //> template  : String = Hello $name  //just for illustration:  val message = s(template)     //> doesn't compile (not found: value s) 
  1. Is there a way to "dynamically" evaluate a String like that? (or is it inherently wrong / not possible)

  2. And what is s exactly? it's not a method def (apparently it is a method on StringContext), and not an object (if it was, it would have thrown a different compile error than not found I think)


like image 786
Eran Medan Avatar asked Nov 06 '12 23:11

Eran Medan


People also ask

What is string interpolation in Scala?

String Interpolation refers to substitution of defined variables or expressions in a given String with respected values. String Interpolation provides an easy way to process String literals. To apply this feature of Scala, we must follow few rules: String must be defined with starting character as s / f /raw.

What is the syntax for string interpolation?

Syntax of string interpolation starts with a '$' symbol and expressions are defined within a bracket {} using the following syntax. Where: interpolatedExpression - The expression that produces a result to be formatted.

Which strings do interpolate variables?

String interpolation is common in many programming languages which make heavy use of string representations of data, such as Apache Groovy, Julia, Kotlin, Perl, PHP, Python, Ruby, Scala, Swift, Tcl and most Unix shells.

Which one is interpolator in Scala?

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: Scala 2.


2 Answers

s is actually a method on StringContext (or something which can be implicitly converted from StringContext). When you write

whatever"Here is text $identifier and more text" 

the compiler desugars it into

StringContext("Here is text ", " and more text").whatever(identifier) 

By default, StringContext gives you s, f, and raw* methods.

As you can see, the compiler itself picks out the name and gives it to the method. Since this happens at compile time, you can't sensibly do it dynamically--the compiler doesn't have information about variable names at runtime.

You can use vars, however, so you can swap in values that you want. And the default s method just calls toString (as you'd expect) so you can play games like

class PrintCounter {   var i = 0   override def toString = { val ans = i.toString; i += 1; ans } }  val pc = new PrintCounter def pr[A](a: A) { println(s"$pc: $a") } scala> List("salmon","herring").foreach(pr) 1: salmon 2: herring 

(0 was already called by the REPL in this example).

That's about the best you can do.

*raw is broken and isn't slated to be fixed until 2.10.1; only text before a variable is actually raw (no escape processing). So hold off on using that one until 2.10.1 is out, or look at the source code and define your own. By default, there is no escape processing, so defining your own is pretty easy.

like image 92
Rex Kerr Avatar answered Oct 25 '22 09:10

Rex Kerr


Here is a possible solution to #1 in the context of the original question based on Rex's excellent answer

val name = "World"                  //> name: String = World val template = name=>s"Hello $name" //> template: Seq[Any]=>String = <function1> val message = template(name)        //> message: String = Hello World 
like image 38
Eran Medan Avatar answered Oct 25 '22 10:10

Eran Medan