Scala字符串插值 - StringContext
简介
自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的更多相关文章
- Scala字符串插值
Scala提供了三种字符串插值方式:s,f和raw.1. s字符串插值器简单的说就是解析字符串变量. val name = "Tom" println(s"His nam ...
- [转] Scala 2.10.0 新特性之字符串插值
[From] https://unmi.cc/scala-2-10-0-feature-string-interpolation/ Scala 2.10.0 新特性之字符串插值 2013-01-20 ...
- scala字符串前加s使用$
https://my.oschina.net/u/2000675/blog/1592140 字符串中的变量替换,Scala中基础的字符串插值就是在字符串前加字幕‘s’,然后在字符串中放入变量,每个变量 ...
- Spark记录-Scala字符串
Scala字符串 在Scala中的字符串和Java中的一样,字符串是一个不可变的对象,也就是一个不能修改的对象.可以修改的对象,如数组,称为可变对象.字符串是非常有用的对象,在本节的最后部分,我们将介 ...
- angularjs字符串插值($interpolate)
<!DOCTYPE html> <html lang="zh-CN" ng-app="app"> <head> <me ...
- Swift字符串插值
字符串插值是一种全新的构建字符串的方式,可以在其中包含常量.变量.字面量和表达式.您插入的字符串字面量的每一项都被包裹在以反斜线为前缀的圆括号中: let multiplier = let messa ...
- Scala:字符串
http://blog.csdn.net/pipisorry/article/details/52902348 Scala字符串 在 Scala 中,字符串的类型实际上是 Java String,它本 ...
- CoffeeScript里的字符串插值
拼接字符串是我们常干的事情.与其用很多的 "" + "",不如用一下字符串插值,可读性好些. 方法是在字符串中加入#{ 变量.表达式.函数等} getOther ...
- React技巧之字符串插值
原文链接:https://bobbyhadz.com/blog/react-string-interpolation 作者:Borislav Hadzhiev 正文从这开始~ 总览 在React中,使 ...
随机推荐
- 来迟了,用Python助你叠猫猫,抢618大红包!
目录: 0 引言 1 环境 2 需求分析 3 前置准备 4 逛店铺流程回顾 5 代码全景展示 6 总结 0 引言 最近叠猫猫的活动可真是十分的火爆,每天小伙伴们为了合猫猫忙的可谓是如火如荼.为啥要叠猫 ...
- FreeMarker实现网页静态化
1.FreeMarker实现网页静态化. FreeMarker是一个用Java语言编写的模板引擎,它基于模板来生成文本输出.FreeMarker与Web容器无关,即在Web运行时,它并不知道Servl ...
- 使用AspectCore实现AOP模式的Redis缓存
这次的目标是实现通过标注Attribute实现缓存的功能,精简代码,减少缓存的代码侵入业务代码. 缓存内容即为Service查询汇总的内容,不做其他高大上的功能,提升短时间多次查询的响应速度,适当减轻 ...
- python 错误、调试、单元测试、文档测试
错误分为程序的错误和由用户错误的输入引起的错误,此外还有因为各种各样意外的情况导致的错误,比如在磁盘满的时候写入.从网络爬取东西的时候,网络断了.这类错误称为异常 错误处理 参考链接:https:// ...
- Java开发中对Redis的基本操作
Jedis操作redis指令 import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; impo ...
- 读oc52个有效方法的总结
这本书主要是对于oc语言的代码优化和一些我们不知道的精华.全书分为7章节 1.熟悉oc语言 第一条:了解oc的语言起源 主要是对于oc语言的起源介绍和oc语言的特点进行概括,oc语言主要是使用消息结构 ...
- Jsp调用淘宝IP地址库获取来访IP详细信息
Jsp调用淘宝IP地址库获取来访IP详细信息 示例网页点击:www.trembler.cn/ipinfo/ipinfo(服务器有其他用处,页面已失效) String ip = request.ge ...
- 章节十一、6-操作集合里面的Web元素
以下演示操作以该网站为例:https://learn.letskodeit.com/p/practice 一.如何操作多个元素(把多个元素放到集合容器中然后操作它们) 列如我们需要操作这些单选框:: ...
- Mac启动MySQL
启动MySQL服务 sudo /usr/local/Cellar/mysql//bin/mysql.server start 停止MySQL服务 sudo /usr/local/Cellar/mysq ...
- Docker镜像服务(二)
一.Docker镜像介绍 镜像是Docker的三大核心概念之一. Docker运行容器前需要本地存在对应的镜像,如果镜像不存在本地,Docker会尝试先从默认的镜像仓库下载(默认使用Docker Hu ...