Scala ひと巡り : 抽出子オブジェクト (Extractor Objects)

Scala では、パターンをケースクラスとは独立に定義できます。この目的のために、unapply という名前のメソッドを定義することで、いわゆる抽出子がもたらされます。

例えば、次のコードは抽出子オブジェクト Twice を定義します。

object Twice { def apply(x: Int): Int = x * 2 def unapply(z: Int): Option[Int] = if (z%2 == 0) Some(z/2) else None } object TwiceTest extends Application { val x = Twice(21) x match { case Twice(n) => Console.println(n) } // prints 21 }

次は、ここで関係する 2 つの文法上の規約(convention)です:

    • パターン case Twice(n)は、Twice.unapply の呼び出しを引き起こし、偶数のマッチに使われます。; unapply の戻り値は、引数がマッチしたかどうか、そしてさらなるマッチングのために使えるサブ値を伝えます。ここで、サブ値は z/2 です。

    • The apply method is not necessary for pattern matching. It is only used to mimic a constructor val x = Twice(21) expands to val x = Twice.apply(21) .

    • apply メソッドは、パターンマッチングについては必須ではありません。これはただ、コンストラクタをまねて val x = Twice(21) を val x = Twice.apply(21) へ展開する時に使われるだけです。

unapply の戻り値型は、次のように選ぶべきです:

    • もしそれが単なるテストなら、Boolean を返す。たとえば case even() 。

    • もしそれがただ一つの、型 T のサブ値を返すなら、Option[T]を返す。

    • もし複数のサブ値 T1,...,Tn を返したいなら、それらをまとめてタプルのオプション Option[(T1,...,Tn)]として返す。

しばしば、サブ値の数が固定で、シーケンスを返したいことがあります。その場合は、unapplySeq を介して同様にパターンを定義できます。最後のサブ値の型 Tn は、Seq[S]でなければなりません。このメカニズムは、たとえば、パターン case List(x1,...,xn) 中で使われます。

抽出子を使えば、コードはさらに保守しやすくなります。詳細は、Emir [56]、Odersky[57] と Williams (2007 年 1 月) らによる論文「パターンを用いたオブジェクトマッチング」[55](4 章参照) を読んでください。