Scala 2.10中的string插值 – 如何内插一个stringvariables?

从Scala 2.10开始,Scala中可以使用string插值

这是基本的例子

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

我想知道是否有一种方法来做dynamic插值,例如下面的(不会编译,仅用于说明目的)

  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. 有没有办法“dynamic”评估一个string呢? (或者它本身是错误的/不可能的)

  2. 那究竟是什么? 这不是一个方法def ( 显然这是一个StringContext上的方法 ),而不是一个对象(如果是的话,它会引发一个不同的编译错误比我不认为)


s实际上是一个在StringContext上的方法(或者可以从StringContext隐式转换的方法)。 当你写

 whatever"Here is text $identifier and more text" 

编译器把它parsing成

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

默认情况下, StringContext为你提供了sfraw *方法。

正如你所看到的,编译器自己挑出名字并将其提供给方法。 由于这是在编译时发生的,因此不能dynamic地做到这一点 – 编译器在运行时没有关于variables名的信息。

然而,你可以使用variables,所以你可以交换你想要的值。 而默认s方法只是调用toString (如你所期望的),所以你可以玩类似的游戏

 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 

(在这个例子中,REPL已经调用了0)。

这是关于你能做的最好的。

* raw破碎,直到2.10.1才被固定; 只有variables之前的文本实际上是原始的(没有转义处理)。 所以暂缓使用那个,直到2.10.1出来,或者查看源代码并定义你自己的。 默认情况下,没有转义处理,所以定义你自己很容易。

根据Rex的出色答案,在原始问题的背景下,这是一个可能的解决scheme

 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 
  1. string插值发生在编译时,所以编译器通常没有足够的信息来插入s(str) 。 它期望一个string文字, 根据SIP 。
  2. 在您链接的文档中,在“ 高级用法”下,解释了表单id"Hello $name ."的expression式id"Hello $name ." 在编译时转换为new StringContext("Hello", "."). id(name) new StringContext("Hello", "."). id(name)

请注意, id可以是通过隐式类引入的用户定义的插补器。 该文档给出了一个json插补器的例子,

 implicit class JsonHelper(val sc: StringContext) extends AnyVal { def json(args: Any*): JSONObject = { ... } } 

在当前的实现中,这本质上是不可能的:局部variables名在执行时不可用 – 可以作为debugging符号保留,但也可以被剥离。 (成员variables名称,但这不是你在这里描述的)。