代码之家  ›  专栏  ›  技术社区  ›  BlueDolphin

如何在变量上应用Scala字符串插值?[副本]

  •  0
  • BlueDolphin  · 技术社区  · 6 年前

    字符串插值是 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 确切地 这不是一种方法 ( apparently it is a method on StringContext ),而不是对象(如果是,则会抛出与 找不到 (我想)


    0 回复  |  直到 8 年前
        1
  •  38
  •   Elnur Abdurrakhimov Jon Skeet    12 年前

    s 这实际上是一种方法 StringContext (或可以隐式转换为 StringContext ).当你写作的时候

    whatever"Here is text $identifier and more text"
    

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

    默认情况下, StringContext 给你 s f raw *方法。

    如您所见,编译器本身选择名称并将其提供给方法。因为这是在编译时发生的,所以您不能明智地动态地执行它——编译器在运行时没有关于变量名的信息。

    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
    

    这是你能做的最好的了。

    * 未经加工的 已损坏且在2.10.1之前不会修复;只有变量前的文本才是原始文本(无转义处理)。因此,在2.10.1发布之前不要使用该版本,或者查看源代码并定义自己的版本。默认情况下,没有转义处理,因此定义自己的转义处理非常容易。

        2
  •  14
  •   Eran Medan    12 年前

    根据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
    
        3
  •  7
  •   Kipton Barros tanza9    12 年前
    1. 字符串插值发生在编译时,因此编译器通常没有足够的信息进行插值 s(str) according to the SIP .
    2. 在下面 高级用法 在您链接的文档中,解释了表单的表达式 id"Hello $name ." 在编译时转换为 new StringContext("Hello", "."). id(name) .

    注意 id 可以是通过隐式类引入的用户定义的插值器。文档中给出了一个示例 json

    implicit class JsonHelper(val sc: StringContext) extends AnyVal {
      def json(args: Any*): JSONObject = {
        ...
      }
    }
    
        4
  •  1
  •   jsalvata    12 年前

    这在当前的实现中本质上是不可能的:局部变量名在执行时不可用——可以作为调试符号保留,但也可以被删除。(成员变量名是,但这不是您在这里描述的内容)。