翻译自:STRING INTERPOLATION

简介

自2.10.0版本开始,Scala提供了一种新的机制来根据数据生成字符串:字符串插值。字符串插值允许使用者将变量引用直接插入处理过的字面字符中。如下例:

val name="James"
println(s"Hello,$name")//Hello,James

在上例中, s”Hello,$name” 是待处理字符串字面,编译器会对它做额外的工作。待处理字符串字面通过“号前的字符来标示(例如:上例中是s)。字符串插值的实现细节在 SIP-11 中有全面介绍。

用法

Scala 提供了三种创新的字符串插值方法:s,f 和 raw.

s 字符串插值器

在任何字符串前加上s,就可以直接在串中使用变量了。你已经见过这个例子:

val name="James"
println(s"Hello,$name")//Hello,James 此例中,$name嵌套在一个将被s字符串插值器处理的字符串中。插值器知道在这个字符串的这个地方应该插入这个name变量的值,以使输出字符串为Hello,James。使用s插值器,在这个字符串中可以使用任何在处理范围内的名字。

字符串插值器也可以处理任意的表达式。例如:

println(s"1+1=${1+1}") 将会输出字符串1+1=2。任何表达式都可以嵌入到${}中。

f 插值器

在任何字符串字面前加上 f,就可以生成简单的格式化串,功能相似于其他语言中的 printf 函数。当使用 f 插值器的时候,所有的变量引用都应当后跟一个printf-style格式的字符串,如%d。看下面这个例子:

val height=1.9d
val name="James"
println(f"$name%s is $height%2.2f meters tall")//James is 1.90 meters tall f 插值器是类型安全的。如果试图向只支持 int 的格式化串传入一个double 值,编译器则会报错。例如: val height:Double=1.9d
scala>f"$height%4d"
<console>:: error: type mismatch;
found : Double
required: Int
f"$height%4d"
^ f 插值器利用了java中的字符串数据格式。这种以%开头的格式在 [Formatter javadoc] 中有相关概述。如果在具体变量后没有%,则格式化程序默认使用 %s(串型)格式。

raw 插值器

除了对字面值中的字符不做编码外,raw 插值器与 s 插值器在功能上是相同的。如下是个被处理过的字符串:

scala>s"a\nb"
res0:String=
a
b 这里,s 插值器用回车代替了\n。而raw插值器却不会如此处理。 scala>raw"a\nb"
res1:String=a\nb 当不想输入\n被转换为回车的时候,raw 插值器是非常实用的。

除了以上三种字符串插值器外,使用者可以自定义插值器。

高级用法

在Scala中,所有处理过的字符串字面值都进行了简单编码转换。任何时候编译器遇到一个如下形式的字符串字面值:

id"string content" 它都会被转换成一个StringContext实例的call(id)方法。这个方法在隐式范围内仍可用。只需要简单得 建立一个隐类,给StringContext实例增加一个新方法,便可以定义我们自己的字符串插值器。如下例:

//注意:为了避免运行时实例化,我们从AnyVal中继承。
//更多信息请见值类的说明
implicit class JsonHelper(val sc:StringContext) extends AnyVal{
def json(args:Any*):JSONObject=sys.error("TODO-IMPLEMENT")
} def giveMeSomeJson(x:JSONObject):Unit=... giveMeSomeJson(json"{name:$name,id:$id}") 在这个例子中,我们试图通过字符串插值生成一个JSON文本语法。隐类 JsonHelper 作用域内使用该语法,且这个JSON方法需要一个完整的实现。只不过,字符串字面值格式化的结果不是一个字符串,而是一个JSON对象。

当编译器遇到”{name:$name,id:$id”}”,它将会被重写成如下表达式:

new StringContext("{name:",",id:","}").json(name,id)

隐类则被重写成如下形式

new JsonHelper(new StringContext("{name:",",id:","}")).json(name,id)

所以,JSON方法可以访问字符串的原生片段而每个表达式都是一个值。这个方法的一个简单但又令人迷惑的例子:

implicit class JsonHelper(val sc:StringContext) extends AnyVal{
def json(args:Any*):JSONObject={
val strings=sc.parts.iterator
val expressions=args.iterator
var buf=new StringBuffer(strings.next)
while(strings.hasNext){
buf append expressions.next
buf append strings.next
}
parseJson(buf)
}
}

被处理过的字符串的每部分都是StringContext的成员。每个表达式的值都将传入到JSON方法的args参数。JSON方法接受这些值并合成一个大字符串,然后再解析成JSON格式。有一种更复杂的实现可以避免合成字符串的操作,它只是简单的直接通过原生字符串和表达式值构建JSON。

限制

字符串插值目前对模式匹配语句不适用。此特性将在2.11版本中生效。

自定义字符串插值函数

自定义字符串插值函数:

package test.interpolator

/**
* 类功能描述:
*
* @author WangXueXing create at 19-5-3 下午9:54
* @version 1.0.0
*/
case object StringU{
implicit class SLStringContext(sc: StringContext) {
def sl(args: String*):String = sc.parts.mkString(",")+" : "+args.mkString(",")
}
}
使用自定义插值函数:
package test.interpolator

import test.interpolator.StringU._
/**
* 类功能描述:
*
* @author WangXueXing create at 19-5-3 下午9:57
* @version 1.0.0
*/
object StringTest {
def main(args: Array[String]): Unit = {
val i = 23
val j = "hello"
val sss = sl"""24:${j}2424${i.toString}"""
println(sss)
}
}

输出结果:

:,, : hello,

Scala字符串插值 - StringContext的更多相关文章

  1. Scala字符串插值

    Scala提供了三种字符串插值方式:s,f和raw.1. s字符串插值器简单的说就是解析字符串变量. val name = "Tom" println(s"His nam ...

  2. [转] Scala 2.10.0 新特性之字符串插值

    [From]  https://unmi.cc/scala-2-10-0-feature-string-interpolation/ Scala 2.10.0 新特性之字符串插值 2013-01-20 ...

  3. scala字符串前加s使用$

    https://my.oschina.net/u/2000675/blog/1592140 字符串中的变量替换,Scala中基础的字符串插值就是在字符串前加字幕‘s’,然后在字符串中放入变量,每个变量 ...

  4. Spark记录-Scala字符串

    Scala字符串 在Scala中的字符串和Java中的一样,字符串是一个不可变的对象,也就是一个不能修改的对象.可以修改的对象,如数组,称为可变对象.字符串是非常有用的对象,在本节的最后部分,我们将介 ...

  5. angularjs字符串插值($interpolate)

    <!DOCTYPE html> <html lang="zh-CN" ng-app="app"> <head> <me ...

  6. Swift字符串插值

    字符串插值是一种全新的构建字符串的方式,可以在其中包含常量.变量.字面量和表达式.您插入的字符串字面量的每一项都被包裹在以反斜线为前缀的圆括号中: let multiplier = let messa ...

  7. Scala:字符串

    http://blog.csdn.net/pipisorry/article/details/52902348 Scala字符串 在 Scala 中,字符串的类型实际上是 Java String,它本 ...

  8. CoffeeScript里的字符串插值

    拼接字符串是我们常干的事情.与其用很多的 "" + "",不如用一下字符串插值,可读性好些. 方法是在字符串中加入#{ 变量.表达式.函数等} getOther ...

  9. React技巧之字符串插值

    原文链接:https://bobbyhadz.com/blog/react-string-interpolation 作者:Borislav Hadzhiev 正文从这开始~ 总览 在React中,使 ...

随机推荐

  1. Spring Cloud Ribbon客户端负载均衡(四)

    序言 Ribbon 是一个客户端负载均衡器(Nginx 为服务端负载均衡),它赋予了应用一些支配 HTTP 与 TCP 行为的能力,可以得知,这里的客户端负载均衡也是进程内负载均衡的一种.它在 Spr ...

  2. 机器学习(十一)-------- 异常检测(Anomaly Detection)

    异常检测(Anomaly Detection) 给定数据集

  3. SqlServer 创建数据库两种方式

    一个SqlServer 数据库实例大概可以创建三万多个数据库. 创建数据库的第一种方式:SqlServer Management Studio管理工具进行可视化创建. 1).打开数据库管理工具,在&q ...

  4. RSA应用指数与模生成公钥(ArcGIS Server)

    参考: https://www.cnblogs.com/luo30zhao/p/10515594.html https://blog.csdn.net/skiof007/article/details ...

  5. 练手WPF(二)——2048游戏的简易实现(下)

    接着上一篇继续~~~ 6.动画显示增加分数 /// <summary> /// 动画显示增加得分 /// </summary> /// <param name=" ...

  6. winfrom 获取焦点控件

    [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Win ...

  7. PIE SDK水体指数法

    1.算法功能简介 单波段阈值法是通过选择某单一波段为判识参数,这一波段往往是水体特征最明显而其它地物相对不太突出的波段(如近红外波段和中红外波段),然后再划定阈值来确定水体信息.该方法主要是利用水体在 ...

  8. Gitlab的CI/CD初尝试

    初衷:今天公司的前端和测试人员吵起来了.原因是测试埋怨前端人员把Bug的状态更改为已解决,结果代码根本没提交,而前端人员埋怨测试测的太频繁了,需要打几个环境的包不方便.又要改东西又要频繁打包费时间.凡 ...

  9. JavaScript中的 JSON 和 JSONP

    JSON 和 JSONP JSONP是一种发送JSON数据的方法,无需担心跨域问题.JSONP不使用该XMLHttpRequest对象.JSONP使用<script>标签代替.由于跨域策略 ...

  10. django中添加新的filter

    给模板传递了一个字典,却发现无法在模板中直接通过key获得value. 查阅资料后,这个问题可以通过添加自定义的filter来解决. 首先在app目录下创建一个templatetags目录,并在它的下 ...