自定义scala 字符串插值

前言

字符串插值是 scala 2.10.0 开始引入的一个新的概念,就是能够让用户在字符串中嵌入变量引用。

从而可以让用户用数据来构造字符串。

比如 s interpolator,允许直接在字符串中使用变量和计算表达式:

val name = "Ldpe2G"
println(s"Hello, $name")  // Hello, Ldpe2G
println(s"1 + 1 = ${1 + 1}") // 1 + 1 = 2

已经提供的interpolator还有f, raw等

参考:http://docs.scala-lang.org/overviews/core/string-interpolation.html

正文

下面我们来看看如何自定义一个字符串插值,比如,从一个字符串中找到所有的email地址,

虽然用字符串插值来实现这个功能可能是多此一举,写个函数就可以解决。我这里只是为了

举例如何自定义字符串插值。

import scala.language.experimental._

object EmailTest {

    def main(args: Array[String]) = {
  	  val email = "test@gmail.com,test@163.com:fakee3rerw@qq.com"
  	  //为StringContext添加了一个emails方法
  	  //见下面的 implicit class EmailHelper 
  	  val emails = emails"测试${email}测试" 
  	  emails.filter(!_.equals("")).foreach(println)
    }
  
  //email正则表达式,取自 http://tool.oschina.net/
   val emailR = """[\w!#$%&'*+/=?^_`{|}~-]+(?:\.[\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?""".r
    
   implicit class EmailHelper(val sc: StringContext) extends AnyVal {
      def emails(args: Any*): List[String] = {
          val strings = sc.parts.iterator
          val expressions = args.iterator
          val emails1 = (List[String]() /: strings)((acc, elem) => {
              val mats = emailR.findAllIn(elem) mkString(",") split(",") 
              acc ::: mats.toList
          })
          val emails2 = (List[String]() /: expressions)((acc, elem) => {
              val mats = emailR.findAllIn(sc.s(elem)) mkString(",") split(",") 
              acc ::: mats.toList
          })
         emails1 ::: emails2
      }
  }
  
}

代码解释:

下面一句代码:

emails"测试${email}测试"

被编译器重写为:

new EmailHelper(new StringContext("测试", "测试")).emails(email)

字符串插值和scala macro结合起来还可以实现很多功能。比如在编译时期判断字符串是否一个合法的email地址。

由于macro我还在学习中,等学习完了再写一篇博客。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏mathor

TRIE(2)

 其中MAX_NODE是trie中最大能存储的节点数目,CHARSET是字符集的大小,k是当前trie中包含有多少个节点。Triei的值是0表示trie树中i号...

13530
来自专栏逆向技术

逆向知识第六讲,取摸优化的几种方式

        逆向知识第六讲,取摸优化的几种方式 除法讲完之后,直接开始讲 % 运算符在汇编中表现形式 首先C的高级代码贴上来. 高级代码: // Tedy....

209100
来自专栏哲学驱动设计

重构一个繁琐的数据结构

    在GIX4项目的开发过程中,遇到一个比较复杂的数据结构。复杂,是因为它有许多限制条件。我的工作是在现有系统中,添加新的功能,并在过程中重构部分旧代码。 ...

254100
来自专栏hbbliyong

c++ list, vector, map, set 区别与用法比较

List封装了链表,Vector封装了数组, list和vector得最主要的区别在于vector使用连续内存存储的,他支持[]运算符,而list是以链表形式实...

1.8K90
来自专栏尾尾部落

[剑指offer] 旋转数组的最小数字

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为...

10320
来自专栏我的技术专栏

C++ 顺序容器基础知识总结

22150
来自专栏人工智能LeadAI

共享变量 tensorflow解读

你可以在怎么使用变量中所描述的方式来创建,初始化,保存及加载单一的变量.但是当创建复杂的模块时,通常你需要共享大量变量集并且如果你还想在同一个地方初始化这所有的...

12820
来自专栏闪电gogogo的专栏

【数据结构(C语言版)系列四】 串

串(或字符串)是由零个或多个字符组成的有限序列,一般记为 s = 'a1a2...an',s为串名。子串在主串中的位置以子串的第一个字符在主串中的位置来表示。

10510
来自专栏AhDung

【手记】注意BinaryWriter写string的小坑——会在string前加上长度前缀length-prefixed

之前以为BinaryWriter写string会严格按构造时指定的编码(不指定则是无BOM的UTF8)写入string的二进制,如下面的代码:

32030
来自专栏ppjun专栏

Android十八章:Java硬软弱虚引用,GC回收,内存碎片

又叫java虚拟机栈区,是每一个方法被执行的时候,创建出一个栈帧用来放的成员变量,操作链表,动态链接,方法出口。很多个栈帧又存储在栈区。

16420

扫码关注云+社区

领取腾讯云代金券