1

从 scala 2.10 开始,可以进行以下插值。

val name = "someName"
val interpolated = s"Hello world, my name is $name"

现在也可以定义自定义字符串插值,您可以在http://docs.scala-lang.org/overviews/core/string-interpolation.html#advanced_usage的“高级用法”部分的 scala 文档中看到

那么,我的问题是......有没有办法在插值之前从定义字符串新插值的隐式类内部获取原始字符串,包括任何插值变量名称?

换句话说,我希望能够定义一个插值 x,这样当我调用

x"My interpolated string has a $name"

我可以完全如上所示获得字符串,而无需在插值内替换 $name 部分。

编辑:快速说明,我想这样做的原因是因为我想获取原始字符串并将其替换为另一个字符串,一个国际化字符串,然后替换变量值。这是我想获得原始字符串而不对其执行插值的主要原因。

提前致谢。

4

3 回答 3

3

由于 Scala 的字符串插值可以处理其中的任意表达式,${}因此必须在将参数传递给格式化函数之前对其进行评估。因此,设计上不可能直接访问变量名。正如 Eugene 所指出的,可以通过使用宏来获取普通变量的名称。不过,我认为这不是一个非常可扩展的解决方案。毕竟,您将失去对任意表达式求值的可能性。例如,在这种情况下会发生什么:

x"My interpolated string has a ${"Mr. " + name}"

您也许可以通过使用宏来提取变量名称,但对于任意表达式可能会变得复杂。我的建议是:如果您的变量名称在字符串插值中应该是有意义的,请将其作为数据结构的一部分。例如,您可以执行以下操作:

case class NamedValue(variableName: String, value: Any)

val name = NamedValue("name", "Some Name")

x"My interpolated string has a $name"

对象被传递Any*x. 因此,您现在可以匹配NamedValue内部x,并且您可以根据“变量名称”做特定的事情,它现在是您的数据结构的一部分。除了显式存储变量名,您还可以利用类型层次结构,例如:

sealed trait InterpolationType
case class InterpolationTypeName(name: String) extends InterpolationType
case class InterpolationTypeDate(date: String) extends InterpolationType

val name = InterpolationTypeName("Someone")
val date = InterpolationTypeDate("2013-02-13")
x"$name is born on $date"

同样,x您可以在其中匹配InterpolationType子类型并根据类型处理事情。

于 2013-02-13T11:55:56.790 回答
2

这似乎是不可能的。字符串插值似乎是一种编译功能,可将示例编译为:

StringContext("My interpolated string has a ").x(name)

如您所见,该$name部分已经消失了。当我查看以下源代码时,我变得非常清楚StringContexthttps ://github.com/scala/scala/blob/v2.10.0/src/library/scala/StringContext.scala#L1

于 2013-02-11T23:17:54.057 回答
1

如果将 x 定义为宏,那么您将能够看到编译器生成的脱糖树(如 @EECOLOR 所示)。在该树中,“name”参数将被视为 Ident(newTermName(“name”)),因此您将能够从那里提取名称。请务必查看 docs.scala-lang.org 上的宏和反射指南,以了解如何编写宏和使用树。

于 2013-02-12T13:49:55.093 回答