Scala的双字符串插值无法处理转义字符

9avjhtql  于 6个月前  发布在  Scala
关注(0)|答案(1)|浏览(96)

我尝试使用双重/反向字符串插值将字符串分解为值,但如果字符串包含转义字符(如“\t”或“\n”),我会遇到问题。
作为参考,我说的是李浩毅在7387中的scala 2.13中添加的这个特性。
这个例子来自PR作品:

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

字符串
但是,将"\t“或”\n“放入其中会将其破坏:

// '\t'
val s"Hello\t$name" = "Hello\tJames"
// scala.MatchError: Hello James (of class java.lang.String)

// '\n'
val s"Hello\n$name" = "Hello\nJames"
// scala.MatchError: Hello     <---- note error is different to others

// '\r'
val s"Hello\r$name" = "Hello\rJames"
// James (of class java.lang.String)  <---- note weird error that gets thrown here

// '\"'
val s"Hello\"$name" = "Hello\"James"
// scala.MatchError: Hello"James (of class java.lang.String)

// '\\'
val s"Hello\\$name" = "Hello\\James"
// scala.MatchError: Hello\James (of class java.lang.String)


上面的代码是在java 8的WSL上为scala 2.13运行的。我在scala 3和sbt项目中遇到了类似的问题。
这对我来说不是一个拦截器,但我觉得这个功能很有用,我想更好地理解它。我能找到的关于这个功能的唯一文档是在原始PR和scala 2.13 release notes中的一个非常简短的提到。
有些疑问:
1.这是预期的行为、bug还是未定义的行为?PR没有定义这些边缘情况的行为。
1.是否有任何已知的变通办法?
1.这个功能的正式名称是什么?在PR上,浩一称之为“简单字符串插值器的对偶”。知道它的正确名称将有助于我搜索它。
1.还有其他官方文件吗?
这感觉像是一个bug,因为普通插值支持转义,而此功能是它的“对偶”:

val name = "James"

s"Hello\t$name"
// "Hello\tJames"


谢谢你,谢谢

gkl3eglg

gkl3eglg1#

1.这是预期的行为、bug还是未定义的行为?PR没有定义这些边缘情况的行为。
这被认为是一个漏洞-参见issue 12893
它很快就被修复了--请参阅PR 10570
1.是否有任何已知的变通办法?
既然bug已经修复,就不需要太多的变通办法了。
但为了完整起见,正如@Gaël所建议的,可以使用正则表达式:

// Scala 2.13
val afterHello = "Hello\t(.*)".r

val afterHello(name) = "Hello\tJames"
// `name` set to "James"

字符串
在scala 3中,你会得到一个编译器警告,告诉你匹配不是穷举的。

// Scala 3
val afterHello(name) = "Hello\tJames": String @ unchecked


或者使用值得信赖的split

val Array(_, name) = "Hello\tJames".split('\t')


出于某种原因,这个不需要unchecked
1.这个功能的正式名称是什么?在PR上,浩一称之为“简单字符串插值器的对偶”。知道它的正确名称将有助于我搜索它。
我在issue 12893中问到这一点.赛斯说:
在某种程度上,它只是一种方法,而不是一种“功能”;字符串插值是功能,单个插值器是方法。
1.还有其他官方文件吗?
除了最初的公关,似乎没有任何官方文件。
Issue 12893提供了一些关于插值模式如何转换的官方文档的链接。这些文档对一般背景很有帮助,但并没有特别涉及到这个功能。

相关问题