リスト内の各要素を再帰的に操作する次のコードがあります
def doMatch(list: List[Int]): Unit = list match {
case last :: Nil => println("Final element.")
case head :: tail => println("Recursing..."); doMatch(tail)
}
現在、この機能がfilter()およびforeach()を介して利用可能であることを無視すると、これは問題なく機能します。ただし、Seq [Int]を受け入れるように変更しようとすると、問題が発生します。
動作しないことを除いて、コードは次のように見えるはずです。
def doMatch(seq: Seq[Int]): Unit = seq match {
case last +: Seq() => println("Final element.")
case head +: tail => println("Recursing..."); doMatch(tail)
}
編集:たくさんの良い答え! ::は私の例では演算子ではなく、ケースクラスであり、したがって違いであると最初に述べたので、私はagilesteelの答えを受け入れます。
Scalaには2つの_::
_(短所と発音)があります。 1つは_class List
_で定義された演算子で、もう1つは class (List
のサブクラス)です。これは、先頭と末尾で特徴付けられる空でないリストを表します。
_head :: tail
_は、::(head, tail)
から構文的に変更されたコンストラクターパターンです。
_::
_はケースクラスです。つまり、抽出オブジェクトが定義されています。
一種の不正行為ですが、ここにそれがあります:
def doMatch(seq: Seq[Int]): Unit = seq match {
case Seq(x) => println("Final element " + x)
case Seq(x, xs@_*) => println("Recursing..." + x); doMatch(xs)
}
理由を聞かないでくださいxs*
は機能しません...
2012年3月の時点で、これは2.10以降で動作します。
def doMatch(seq: Seq[Int]): Unit = seq match {
case last +: Seq() => println("Final element.")
case head +: tail => println("Recursing..."); doMatch(tail)
} //> doMatch: (seq: Seq[Int])Unit
doMatch(List(1, 2)) //> Recursing...
//| Final element.
より一般的には、 SeqExtractors のSeq
に、append/prependをミラーリングする2つの異なるhead/tailおよびinit/last分解オブジェクトが追加されました。
List(1, 2) match { case init :+ last => last } //> res0: Int = 2
List(1, 2) match { case head +: tail => tail } //> res1: List[Int] = List(2)
Vector(1, 2) match { case init :+ last => last } //> res2: Int = 2
Vector(1, 2) match { case head +: tail => tail } //> res3: scala.collection.immutable.Vector[Int] = Vector(2)
実際に_+:
_のオブジェクトを定義して、探していることを正確に行うことができます。
_object +: {
def unapply[T](s: Seq[T]) =
if(s.nonEmpty)
Some(s.head, s.tail)
else
None
}
scala> val h +: t = Seq(1,2,3)
h: Int = 1
t: Seq[Int] = List(2, 3)
_
その後、コードは期待どおりに機能します。
これは、h +: t
_がパターンのマッチングに使用されたときに+:(h,t)
と同等であるため機能します。
標準ライブラリには、任意のシーケンスに対するパターンマッチングのサポートはないと思います。ただし、パターンマッチングなしで実行できます。
def doMatch(seq: Seq[Int]) {
if (seq.size == 1) println("final element " + seq(0)) else {
println("recursing")
doMatch(seq.tail)
}
}
doMatch(1 to 10)
ただし、独自の抽出オブジェクトを定義できます。 http://www.scala-lang.org/node/112 を参照してください
object SEQ {
def unapply[A](s:Seq[A]):Option[(A, Seq[A])] = {
if (s.size == 0) None else {
Some((s.head, s.tail))
}
}
}
def doMatch(seq: Seq[Int]) {
seq match {
case SEQ(head, Seq()) => println("final")
case SEQ(head, tail) => {
println("recursing")
doMatch(tail)
}
}
}