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") } reg2
reg2となる。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のエライ人!!