【问题标题】:Get argument names in String Interpolation in Scala 2.10在 Scala 2.10 中的字符串插值中获取参数名称
【发布时间】:2013-02-11 23:00:06
【问题描述】:

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

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

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

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

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

x"My interpolated string has a $name"

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

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

提前致谢。

【问题讨论】:

  • 您的用例是什么?可能有比使用字符串插值更好的解决方案,这是一个相当具体的结构。

标签: string scala scala-2.10 string-interpolation


【解决方案1】:

由于 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。因此,您现在可以在x 中匹配NamedValue,并且您可以根据“变量名称”做特定的事情,它现在是您的数据结构的一部分。除了显式存储变量名称,您还可以利用类型层次结构,例如:

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 子类型并根据类型进行处理。

【讨论】:

  • 谢谢!这是一个很好的解释,你给出了一个优雅的选择。会试试看:)
【解决方案2】:

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

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

如您所见,$name 部分已经消失。当我查看StringContext的源代码时,我真的很清楚:https://github.com/scala/scala/blob/v2.10.0/src/library/scala/StringContext.scala#L1

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 2012-10-26
      • 2014-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-19
      • 2018-10-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多