この記事は
- Scalaスケーラブルプログラミング第2版 (現在の最新版は第3版)の26章「抽出子」を乱読した際の備忘録
結論
- 今まで無自覚に使っていたScalaの正規表現に対する理解が少しだけ深まった
本文
- Scalaの抽出子とは
- unapplyというメソッドを持っているオブジェクト
- 例えば以下のUrlオブジェクトを定義すると コードはScalaスケーラブルプログラミング第2版 26章を参考にした
object Url {
def apply(domain: String, directory: String) = domain + "/" + directory
def unapply(str: String): Option[(String, String)] = {
val bits = str.split("/")
if (bits.length == 2) Some(bits(0), bits(1)) else None
}
}
- こんな感じでマッチングできたりできなかったりする
scala> val Url(domain, directory) = "qiita.com/sunmoonStern"
domain: String = qiita.com
directory: String = sunmoonStern
scala> val Url(domain, directory) = "this is some random sentence" // マッチエラーになる
scala.MatchError: this is some random sentence (of class java.lang.String)
... 28 elided
- ここからが本題
- いちいち対応するケースクラスを作らなくてもできる柔軟なパターンマッチが可能なのは抽出子のおかげらしい
- そのようなものの中でもっとも広く使われているのは正規表現のマッチ
- 例 正規表現による小数のパターンマッチ コードはScalaスケーラブルプログラミング第2版 26章を参考にした
import scala.util.matching.Regex
val Decimal = """(-)?(\d+)(\.\d*)?""".r
val input = "-34.001"
val Decimal(sign, intergerpart, decimalpart) = "-34.001"
// sign: String = -
// intergerpart: String = 34
// decimalpart: String = .001
- Scala Standard Library 2.12.0 - scala.util.matching.Regexで確認するとRegexはunapplySeqという、unapplyの返り値を1個 → 可変個にしたみたいなメソッドを持っていたので、なるほど、と納得した