以下は機能しません。
object Foo {
def union(s: Set[Int], t: Set[Int]): Set[Int] = t match {
case isEmpty => s
case (x:xs) => union(s + x, xs)
case _ => throw new Error("bad input")
}
}
エラー:見つかりません:タイプxs
セット全体でパターンマッチングを行うにはどうすればよいですか?
上手、 x:xs
はタイプx
のxs
を意味するため、機能しません。ただし、残念ながら、セットには定義された順序がないため、マッチセットをパターン化することはできません。または、より実用的には、Set
に抽出機能がないためです。
ただし、いつでも独自に定義できます。
object SetExtractor {
def unapplySeq[T](s: Set[T]): Option[Seq[T]] = Some(s.toSeq)
}
例えば:
scala> Set(1, 2, 3) match {
| case SetExtractor(x, xs @ _*) => println(s"x: $x\nxs: $xs")
| }
x: 1
xs: ArrayBuffer(2, 3)
Set
はcase class
ではなく、unapply
メソッドもありません。
これらの2つのことは、Set
で直接パターンマッチングを行うことができないことを意味します。
(update:Set
に対して独自のextractorを定義しない限り、Danielは正しく彼の答えに示されています)
別の方法を見つける必要があります。折り畳み機能を使用することをお勧めします
def union(s: Set[Int], t: Set[Int]): Set[Int] =
(s foldLeft t) {case (t: Set[Int], x: Int) => t + x}
または、最も明示的な型注釈を回避する
def union(s: Set[Int], t: Set[Int]): Set[Int] =
(s foldLeft t)( (union, element) => union + element )
またはさらに短い
def union(s: Set[Int], t: Set[Int]): Set[Int] =
(s foldLeft t)(_ + _)
これにより、s
の要素がt
に蓄積され、1つずつ追加されます。
折りたたみ
参照が必要な場合は、折り畳み操作の docs を次に示します。
foldLeft[B](z: B)(op: (B, A) ⇒ B): B
二項演算子を開始値とこのセットのすべての要素に左から右に適用します。
注:基になるコレクションタイプが順序付けられていない限り、実行ごとに異なる結果が返される場合があります。または、演算子は結合法則と可換法則です。
B the result type of the binary operator.
z the start value.
op the binary operator.
returns the result of inserting op between consecutive elements of this set, going left to right with the start value z on the left:
op(...op(z, x_1), x_2, ..., x_n)
where x1, ..., xn are the elements of this set.
まず第一に、あなたのisEmpty
は、このコンテキストでは変数であるため、すべてのSet
をキャッチします。定数はScalaの大文字で始まり、この条件が当てはまる場合にのみ定数として扱われます。したがって、小文字は任意のSet
をisEmpty
に割り当てます(あなたはEmptySet
を探していますか?)
見られるように ここ 、パターンマッチングはSet
sにはあまり好ましくないようです。おそらく、Set
をList
またはSeq
(toList
/toSeq
)に明示的に変換する必要があります。
object Foo {
def union(s: Set[Int], t: Set[Int]): Set[Int] = t.toList match {
case Nil => s
case (x::xs) => union(s + x, xs.toSet)
case _ => throw new Error("bad input")
}
}
これは私が思いつくことができるものです:
object Contains {
class Unapplier[T](val t: T) {
def unapply(s: Set[T]): Option[Boolean] = Some(s contains t)
}
def apply[T](t: T) = new Unapplier(t)
}
object SET {
class Unapplier[T](val set: Set[T]) {
def unapply(s: Set[T]): Option[Unit] = if (set == s) Some(Unit) else None
}
def apply[T](ts: T*) = new Unapplier(ts.toSet)
}
val Contains2 = Contains(2)
val SET123 = SET(1, 2, 3)
Set(1, 2, 3) match {
case SET123() => println("123")
case Contains2(true) => println("jippy")
case Contains2(false) => println("ohh noo")
}
t match {
case s if s.nonEmpty => // non-empty
case _ => // empty
}