Scala中的正则表达式和模式匹配第二部分

Jer*_*zig 7 scala pattern-matching

作为这个问题的后续行动

下面是一些使用捕获编译和运行的代码.

val myString = "ACATCGTAGCTGCTAGCTG"

val nucCap = "([ACTG]+)".r

myString match {
   case nucCap(myNuc) => println("dna:"+myNuc)
   case _ => println("not dna")
}

>scala scalaTest.scala 
dna:ACATCGTAGCTGCTAGCTG
Run Code Online (Sandbox Code Playgroud)

这是更简单的代码,没有捕获,不编译.

val myString = "ACATCGTAGCTGCTAGCTG"

val nuc = "[ACGT]+".r

myString match {
     case nuc => println("dna")
     case _ => println("not dna")
}

>scala scalaTest.scala
scalaTest.scala:7: error: unreachable code
Run Code Online (Sandbox Code Playgroud)

似乎匹配应该返回一个布尔值,无论是否使用捕获.这里发生了什么?

Ben*_*mes 8

在您的match块中,nuc是一个模式变量,并不引用nuc封闭范围中的变量.这使得默认情况无法访问,因为简单模式nuc将匹配任何内容.

一对空括号nuc将使语法糖工作并unapplySeq在正则表达式上调用方法:

myString match {
  case nuc() => println("dna")
  case _ => println("not dna")
}
Run Code Online (Sandbox Code Playgroud)

避免这种陷阱的一种方法是重命名nucNuc.从大写字母开始使它成为一个稳定的标识符,因此它引用Nuc封闭范围,而不是被编译器视为模式变量.

val Nuc = "[ACGT]+".r
myString match {
  case Nuc => println("dna")
  case _ => println("not dna")
}
Run Code Online (Sandbox Code Playgroud)

上面会打印"not dna",因为在这里我们只是比较NucmyString,他们是不相等的.这是一个错误,但可能不那么令人困惑!

在这种情况下,添加括号也会产生预期的效果:

myString match {
  case Nuc() => println("dna")
  case _ => println("not dna")
}
// prints "dna"
Run Code Online (Sandbox Code Playgroud)

顺便说一句,它不是一个返回的布尔值,但是Option[List[String]]:

scala> nuc.unapplySeq(myString)
res17: Option[List[String]] = Some(List())
scala> nucCap.unapplySeq(myString)
res18: Option[List[String]] = Some(List(ACATCGTAGCTGCTAGCTG))
Run Code Online (Sandbox Code Playgroud)