Scala 2.10 中的字符串插值 - 如何插入字符串变量?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13260864/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
String interpolation in Scala 2.10 - How to interpolate a String variable?
提问by Eran Medan
String interpolation is available in Scalastarting Scala 2.10
从 Scala 2.10 开始,字符串插值在 Scala 中可用
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)
Is there a way to "dynamically" evaluate a String like that? (or is it inherently wrong / not possible)
And what is
sexactly?it's not a method def(apparently it is a method onStringContext), and not an object (if it was, it would have thrown a different compile error than not foundI think)
有没有办法“动态”评估这样的字符串?(或者它本质上是错误的/不可能)
而究竟是
s什么?这不是一个方法定义(显然它是一个方法StringContext),而不是一个对象(如果是,它会抛出一个不同的编译错误而不是我认为没有找到)
采纳答案by Rex Kerr
sis actually a method on StringContext(or something which can be implicitly converted from StringContext). When you write
s实际上是一种方法StringContext(或可以从 隐式转换的东西StringContext)。当你写
whatever"Here is text $identifier and more text"
the compiler desugars it into
编译器将其脱糖为
StringContext("Here is text ", " and more text").whatever(identifier)
By default, StringContextgives you s, f, and raw* methods.
默认情况下,StringContext给你s,f和raw*方法。
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 smethod just calls toString(as you'd expect) so you can play games like
但是,您可以使用 vars,这样您就可以交换所需的值。默认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
(0 was already called by the REPL in this example).
(在这个例子中 0 已经被 REPL 调用了)。
That's about the best you can do.
这是你能做的最好的事情。
*rawis 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.
*raw已损坏,预计要到 2.10.1 才能修复;只有变量之前的文本实际上是原始的(没有转义处理)。所以在 2.10.1 发布之前不要使用那个,或者查看源代码并定义你自己的。默认情况下,没有转义处理,因此定义您自己的处理非常容易。
回答by Eran Medan
Here is a possible solution to #1 in the context of the original question based on Rex's excellent answer
这是基于 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
回答by Kipton Barros
- String interpolation happens at compile time, so the compiler does not generally have enough information to interpolate
s(str). It expects a string literal, according to the SIP. - Under Advanced Usagein the documentation you linked, it is explained that an expression of the form
id"Hello $name ."is translated at compile time tonew StringContext("Hello", "."). id(name).
- 字符串插值发生在编译时,因此编译器通常没有足够的信息来进行插值
s(str)。根据 SIP,它需要一个字符串文字。 - 在您链接的文档中的高级用法下,解释了该形式的表达式
id"Hello $name ."在编译时被翻译为new StringContext("Hello", "."). id(name).
Note that idcan be a user-defined interpolator introduced through an implicit class. The documentation gives an example for a jsoninterpolator,
请注意,id可以是通过隐式类引入的用户定义的插值器。该文档给出了一个json内插器的例子,
implicit class JsonHelper(val sc: StringContext) extends AnyVal {
def json(args: Any*): JSONObject = {
...
}
}
回答by jsalvata
This is inherently impossible in the current implementation: local variable names are not available at execution time -- may be kept around as debug symbols, but can also have been stripped. (Member variable names are, but that's not what you're describing here).
这在当前的实现中本质上是不可能的:局部变量名称在执行时不可用——可以作为调试符号保留,但也可以被剥离。(成员变量名称是,但这不是您在此处描述的内容)。

