Scalaの旅8抽出器オブジェクト(ExtractorObject)

1916 ワード

Scalaでは,パターンはCase Classとは独立に定義され,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つの構文規則があります.
1.パターンcase Twice(n)はTwiceを呼び出す.unapplyは偶数に一致します.unapplyの戻り値は、パラメータが一致するかどうかを識別します.例では、z/2はマッチングに引き続き使用されます.
2.applyはモードマッチングに必要なものではなく、コンストラクタをシミュレートするために使用されます.val x=Twice(21)はval x=Twiceに等価である.apply(21).
unapplyの戻りクラスはOption[Int]であり,実際には3つの可能性がある.
1.テストのみの場合は、ase even()と同様にBooleanを返します.
2.戻りタイプTセットとの要素のうちの1つを返し、戻りタイプはOption[T]である
3.一連のタイプTの要素T 1を返したい場合、…、Tn,それらを1つのメタグループOption[(T 1,...,Tn)]に組み合わせる.
返される要素の個数が固定されている場合もあれば、シーケンスを返す必要がある場合もあります.最上位のunapplySeqモードがあり、最後の要素TnのタイプはSeq[S]でなければならないので、case List(x 1,...,xn)モードを使用することができます.
実は上の例ですが、パラメータ値が21なのか他の数なのか、出力はいつも自身です.どうして?シミュレータコンストラクタは常に偶数を返すので、出力もそれ自体です.次のように変更できます.
object Twice {                              
  def apply(x: Int): Int = x
  def unapply(z: Int): Option[Int] = if (z%2 == 0) Some(z/2) else None
}

object TwiceTest extends Application {
  val x = Twice(13)
  x match { case Twice(n) => Console.println(n) case _ => Console.println("None")}
}

または
object Twice {                              
  def apply(x: Int): Int = x * 2
  def unapply(z: Int): Option[Int] = if (z%3 == 0) Some(z/2) else None
}

object TwiceTest extends Application {
  val x = Twice(13)
  x match { case Twice(n) => Console.println(n) case _ => Console.println("None")}
}

これはもっと面白いです.Someの定義は次のとおりです.
final case class Some[+A](x: A) extends Option[A] {
  def isEmpty = false
  def get = x
}