Scala 2.10中的字符串插值 - 如何插入String变量?

时间:2012-11-06 23:05:09

标签: scala scala-2.10 string-interpolation

字符串插值是available in Scala,从Scala 2.10开始

这是基本的例子

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

我想知道是否有办法进行动态插值,例如以下(不编译,仅用于说明目的)

 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. 有没有办法动态"动态"像那样评估一个字符串? (或者它本身就是错误/不可能)

  2. 究竟是什么s它不是一个方法def apparently it is a method on StringContext),而不是一个对象(如果是,它会抛出一个不同于找不到的编译错误我认为)


4 个答案:

答案 0 :(得分:33)

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

whatever"Here is text $identifier and more text"

编译器将其篡改为

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

默认情况下,StringContext会为您提供sfraw *方法。

正如您所看到的,编译器本身会选择名称并将其提供给方法。由于这是在编译时发生的,因此您无法动态地执行此操作 - 编译器在运行时没有关于变量名的信息。

但是,您可以使用变量,因此您可以交换所需的值。默认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之前修复;只有变量之前的文本才是实际原始的(没有转义处理)。所以推迟使用那个,直到2.10.1出来,或者查看源代码并定义自己的代码。默认情况下,没有转义处理,因此定义自己的转义非常简单。

答案 1 :(得分:11)

根据Rex的优秀答案,这是原始问题背景下#1的可能解决方案

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

答案 2 :(得分:7)

  1. 字符串插值在编译时发生,因此编译器通常没有足够的信息来插入s(str)。它需要一个字符串文字,according to the SIP
  2. 在您链接的文档中的高级用法下,解释了id"Hello $name ."形式的表达式在编译时被翻译为new StringContext("Hello", "."). id(name)
  3. 请注意,id可以是通过隐式类引入的用户定义插值器。该文档提供了json插补器的示例

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

答案 3 :(得分:1)

这在当前实现中本身是不可能的:本地变量名在执行时不可用 - 可以作为调试符号保留,但也可以被剥离。 (成员变量名称是,但这不是您在此描述的内容)。