scala.util.matching.Regexのバグ?
昨日twitterにPOSTしたんだけど、scalaの正規表現マッチングをパターンマッチングで利用するときに、変な動きをしてるのに気がついた。
同じ正規表現で、グループを含むものと含まないものではマッチングの挙動が異なる。
グループを含む正規表現は、パターンマッチングでちゃんとマッチングするが、含まないものはマッチしない。
scala> val reg1="abc.+$".r
reg1: scala.util.matching.Regex = abc.+$
scala> val reg2="abc(.+)$".r
reg2: scala.util.matching.Regex = abc(.+)$
scala> "abcdef" match {
case reg1(x) => print("reg1")
case reg2(x) => print("reg2")
case _ => print("none")
}
reg2reg2となる。reg1にマッチするはずなのに。なんで?
scala.util.macthing.Regex.scalaのソースを見てみる。
/scala/trunk/src/library/scala/util/matching/Regex.scala – Scala
def unapplySeq(target: Any): Option[List[String]] = target match {
case s: java.lang.CharSequence =>
val m = pattern.matcher(s)
if (m.matches) Some((1 to m.groupCount).toList map m.group)
else None
case Match(s) =>
unapplySeq(s)
case _ =>
None
}パターンを含まない場合、unapplySeqはOption[List[String]] = Some(List())を返すことになる。
この場合、caseでマッチしないと判断されるようだ。
空のListのOptionを返すとfalseと評価される?
ためしに、こんなクラスを書いてみたら、ちゃんとマッチした。
import java.util.regex.{Pattern, Matcher}
class MyRegex(regex: String, groupNames: String*) {
import scala.util.matching.Regex._
val pattern = Pattern.compile(regex)
def unapplySeq(target: Any): Option[List[String]] = target match {
case s: java.lang.CharSequence =>
val m = pattern.matcher(s)
if (m.matches)
if( m.groupCount > 0)
Some((1 to m.groupCount).toList map m.group)
else
Some(List(m.group(0)))
else None
case Match(s) =>
unapplySeq(s)
case _ =>
None
}
}
object MyRegexTest extends Application{
val reg = new MyRegex("abc.+$")
"abcdef" match {
case reg(x) => print("ok:" + x)
case _ => print("ng")
}
}これってバグなの?本家にレポートしたほうがいいの?
教えて、scalaのエライ人!!