読者です 読者をやめる 読者になる 読者になる

( ꒪⌓꒪) ゆるよろ日記

( ゚∀゚)o彡°オパーイ!オパーイ! ( ;゚皿゚)ノシΣ フィンギィィーーッ!!!

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のエライ人!!