Scala自定义字符串插值器
示例
除了内置字符串内插器外,还可以定义自定义字符串内插器。
my"foo${bar}baz"
由编译器扩展为:
new scala.StringContext("foo", "baz").my(bar)
scala.StringContext没有my方法,因此可以通过隐式转换提供。具有与内置s插值器相同行为的自定义插值器将按以下方式实现:
implicit class MyInterpolator(sc: StringContext) { def my(subs: Any*): String = { val pit = sc.parts.iterator val sit = subs.iterator //Noteparts.length==subs.length+1 val sb = new java.lang.StringBuilder(pit.next()) while(sit.hasNext) { sb.append(sit.next().toString) sb.append(pit.next()) } sb.toString } }
并且插值my"foo${bar}baz"将对以下内容进行糖化:
new MyInterpolation(new StringContext("foo", "baz")).my(bar)
注意,插值函数的参数或返回类型没有限制。这使我们走上了一条黑暗的道路,在其中可以创造性地使用插值语法来构造任意对象,如以下示例所示:
case class Let(name: Char, value: Int) implicit class LetInterpolator(sc: StringContext) { def let(value: Int): Let = Let(sc.parts(0).charAt(0), value) } let"a=${4}" //设(a,4) let"b=${"foo"}" //错误:类型不匹配 let"c=" //错误:方法let的参数不足:(值:Int)