48

List(不変の) リストの前に要素を追加するために指定された 2 つのメソッドがあります。

  • +:(実装Seq.+:)、および
  • ::( でのみ定義List)

+:技術的には、より一般的な型シグネチャを持っています—</p>

def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[List[A], B, That]): That
def ::[B >: A](x: B): List[B]

—しかし、ドキュメントメッセージによれば単に である必要があるという暗黙的なものを無視するThatList[B]、署名は同等です。

List.+:とはどう違いList.::ますか?それらが実際に同一である場合+:、具体的な実装に依存することを避けることが好ましいと思いますList。しかし、なぜ別の public メソッドが定義されたのでしょうか? クライアント コードはいつそれを呼び出すのでしょうか?

編集

パターンマッチング用のエクストラクタもありますが、::具体的な方法が気になります。

参照: Scala リスト連結、::: vs ++

4

2 に答える 2

41

両方の方法の違いを判断する最善の方法は、ソース コードを調べることです。

ソース::: _

def ::[B >: A] (x: B): List[B] =
  new scala.collection.immutable.::(x, this)

ソース+:: _

override def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[List[A], B, That]): That = bf match {
  case _: List.GenericCanBuildFrom[_] => (elem :: this).asInstanceOf[That]
  case _ => super.+:(elem)(bf)
}

ご覧のとおり、 forListでは、両方のメソッドがまったく同じことを行います (コンパイラは、引数としてList.canBuildFromCanBuildFromを選択します)。

では、どの方法を使用しますか?+:通常、実装 ( ) よりもインターフェース ( ) を選択します::が、関数型言語の一般的なデータ構造であるためList、広く使用されている独自のメソッドがあります。多くのアルゴリズムは、どのように機能するかを構築していますList。たとえば、Listこれらheadtail操作はすべてO(1). したがって、(単一のメソッドまたはクラスの内部で) をローカルで使用する場合は、固有のメソッドListを選択しても問題ありません。Listしかし、クラス間で通信したい場合、つまりいくつかのインターフェースを書きたい場合は、より一般的なSeqインターフェースを選択する必要があります。

于 2012-08-05T07:40:57.463 に答える
14

+:結果の型を、それが呼び出されたオブジェクトの型とは異なるものにすることができるため、より一般的です。例えば:

scala> Range(1,4).+:(0)
res7: scala.collection.immutable.IndexedSeq[Int] = Vector(0, 1, 2, 3)
于 2012-08-05T07:43:57.983 に答える