Regex и Pattern Matching в Scala Часть II - PullRequest
7 голосов
/ 25 октября 2011

В качестве продолжения этого вопроса

Вот некоторый код, который компилируется и работает правильно, используя перехваты.

val myString = "ACATCGTAGCTGCTAGCTG"

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

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

>scala scalaTest.scala 
dna:ACATCGTAGCTGCTAGCTG

Вот более простой код,без захвата, который не компилируется.

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

Похоже, что сопоставление должно возвращать логическое значение независимо от того, используется ли захват.Что здесь происходит?

1 Ответ

8 голосов
/ 26 октября 2011

В вашем блоке match, nuc является переменной шаблона и не ссылается на nuc во вложенной области видимости. Это делает регистр по умолчанию недоступным, потому что простой шаблон nuc будет соответствовать чему угодно.

Пустая пара скобок в nuc заставит синтаксический сахар работать и вызовет метод unapplySeq в регулярном выражении:

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

Один из способов избежать этой ловушки - переименовать nuc в Nuc. Начиная с заглавной буквы, он становится стабильным идентификатором, так что он ссылается на Nuc во входящей области, а не обрабатывается компилятором как переменная шаблона.

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

Выше будет напечатано "not dna", потому что здесь мы просто сравниваем Nuc с myString, и они не равны. Это ошибка, но, возможно, менее запутанная!

Добавление скобок будет иметь желаемый эффект и в этом случае:

myString match {
  case Nuc() => println("dna")
  case _ => println("not dna")
}
// prints "dna"

Кстати, возвращается не логическое значение, а Option[List[String]]:

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