正規表現クラス

すこし、拡張した。

package ryugate.text

import java.util.regex.Pattern
import java.util.regex.Matcher

object Regexp {
  class RyuString(str:String) {
    def re_match(re:String) = Regexp.re_match(re, str)
  }
  implicit def string2ext(self:String) = new RyuString(self);
  
  def re_match(re:String, str:String) = {
    val ptn = Pattern.compile(re)
    val md = ptn.matcher(str)
    if (md.matches) md else null
  }

  def re_match(re:String)(f:(String => Matcher) => Unit):Unit =
    f( str => re_match(re, str) )
}

class Regexp(ptn:Pattern) {
  def this(str:String) = this(Pattern.compile(str))
  
  def re_match(str:String):Matcher = {
    val md = ptn.matcher(str)
    if (md.matches) md else null
  }
}

使いかたは以下の通り

package ryugate.text

import org.specs._
import ryugate.text.Regexp._

object RegexpSpecification extends Specification {
  "Regexp object" should {
    "re_match(no match)" in {
      val md = Regexp.re_match("hoge", "10")
      md must beNull
    }

    "re_match(match)" in {
      val md = Regexp.re_match("10", "10")
      md.toString must be_==("java.util.regex.Matcher[pattern=10 region=0,2 lastmatch=10]")
    }
    
    "re_match(match)" in {
      val md = Regexp.re_match("[0-9]+", "10")
      md must notBeNull
    }

    "re_match with block" in {
      Regexp.re_match("10") {reg_fun =>
        val md = reg_fun("10")
        md.toString must notBeNull
      }
    }
  }

  "Regexp class" should {
    "re_match(no match)" in {
      val reg = new Regexp("hoge")
      val md = reg.re_match("10")
      md must beNull
    }

    "re_match(match)" in {
      val reg = new Regexp("[0-9]+")
      val md = reg.re_match("10")
      md must notBeNull
    }
  }

  "RyuString" should {
    "re_match(no match)" in {
      val str = "hoge"
      val md = str.re_match("hoge")
      md must notBeNull
    }
  }
}

implicitはimportされると有効になる。
通常はObjectの中に置くべき。

なぜなら、implicitを有効にするインポートは
通常「import hoge.Piyo._」 と言う形になるが、
Piyo が classだった場合はメンバは同時にインポートされないため、
不都合が生じる。