3

引数として a を取得し、これを val メンバーとしてSeq[_]不変のクラス インスタンスを返す関数があります。Seqが変更可能である場合Seq、戻りクラスのインスタンスを変更できないことを保証するために、防御的なコピーを作成したいのは明らかです。

このパターンのベスト プラクティスは何ですか? まず、関数をオーバーロードできないことに驚きました

  def fnc(arg: immutable.Seq[_]) = ...
  def fnc(arg: mutable.Seq[_]) = ...

パターンマッチもできます:

  def fnc(arg: Seq[_]) = arg match {
    case s: immutable.Seq[_] => { println("immutable"); s}
    case s: mutable.Seq[_] => {println("mutable"); List()++s }
    case _: ?
  }   

しかし、私はその_ケースについて確信が持てません。argまたは であることが保証されていますimmutable.Seqmutable.Seq? List()++sまた、それを変換する正しい方法であるかどうかもわかりません。SOに関する多くの投稿を見ましたが、それらのほとんどは2.8以前のものです。

Scala-Collections は「インテリジェント」で、いつでも (パターン マッチングなしで) 書き込みList()++s、不変の場合は同じインスタンスを取得し、可変の場合はディープ コピーを取得できますか?

これを行うための推奨される方法は何ですか?

4

3 に答える 3

4

両方をサポートしたい場合は、パターン マッチが必要になります。のコードは、(その API の一部として) 不変の場合、残りをコピーしないことを保証Seq() ++しません。

scala> val v = Vector(1,2,3)
v: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3)

scala> Seq() ++ v
res1: Seq[Int] = List(1, 2, 3)

いくつかの特殊なケースではそれ自体がパターン マッチする場合がありますが、必要なケースはわかっています。そう:

def fnc[A](arg: Seq[A]): Seq[A] = arg match {
  case s: collection.immutable.Seq[_] => arg
  case _ => Seq[A]() ++ arg
}

_;について心配する必要はありません。これは、型引数が何であるかを正確に気にしないことを示しているだけです (とにかくチェックできるというわけではありません)。

于 2013-01-13T17:46:26.993 に答える
1

このパターンのベスト プラクティスは何ですか?

不変性を保証したい場合のベストプラクティスは、防御的なコピーを作成するか、require を作成することですimmutable.Seq

しかし、_ の場合についてはよくわかりません。arg が immutable.Seq または mutable.Seq であることが保証されていますか?

必ずというわけではありませんが、継承するすべての標準ライブラリコレクションcollection.Seqは、これら 2 つのいずれかからも継承されると思います。ただし、カスタム コレクションは、理論的にはcollection.Seq. パターン マッチング ソリューションの改善については、Rex の回答を参照してください。

Scala-Collections は、常に (パターン マッチングなしで) List()++ を記述できるほど「インテリジェント」であり、不変の場合は同じインスタンスを取得し、可変の場合はディープ コピーを取得しますか?

特定のケースではそうですが、他のケースではそうではないようです。たとえば、次のようになります。

val immutableSeq = Seq[Int](0, 1, 2)
println((Seq() ++ immutableSeq) eq immutableSeq) // prints true
val mutableSeq = mutable.Seq[Int](0, 1, 2)
println((Seq() ++ mutableSeq) eq mutableSeq) // prints false

eq参照の等価性はどこにありますか。上記は にも機能しますがList() ++ s、Rex が指摘したように、Vector.

于 2013-01-13T09:39:06.117 に答える
0

あなたは確かにそのように過負荷にすることができます! たとえば、これは問題なくコンパイルされます。

object  MIO
{
  import collection.mutable

  def f1[A](s: Seq[A]) = 23
  def f1[A](s: mutable.Seq[A]) = 42

  def f2(s: Seq[_]) = 19
  def f2(s: mutable.Seq[_]) = 37
}

REPL では:

Welcome to Scala version 2.10.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_37).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import rrs.scribble.MIO._; import collection.mutable.Buffer
import rrs.scribble.MIO._
import collection.mutable.Buffer

scala> f1(List(1, 2, 3))
res0: Int = 23

scala> f1(Buffer(1, 2, 3))
res1: Int = 42

scala> f2(List(1, 2, 3))
res2: Int = 19

scala> f2(Buffer(1, 2, 3))
res3: Int = 37
于 2013-01-13T15:53:12.547 に答える