31

バックグラウンドから来てJava、私はコレクションを扱う一般的な慣行に慣れています: 明らかに例外がありますが、通常、コードは次のようになります:

public class MyClass {
  private Set<String> mySet;

  public void init() {
    Set<String> s = new LinkedHashSet<String>();
    s.add("Hello");
    s.add("World"); 
    mySet = Collections.unmodifiableSet(s);
  }
}

私は、Scala のオプションの多さに少し当惑していることを告白しなければなりません。がある:

  • scala.List(およびSeq)
  • scala.collections.Set(およびMap)
  • scala.collection.immutable.Set(そしてMapStackしかしそうではないList
  • scala.collection.mutable.Set(そしてMapBufferしかしそうではないList
  • scala.collection.jcl

質問です!

  1. およびがパッケージListで定義されていて、定義されていない のはなぜですか(の実装はコレクションのサブパッケージにあるにもかかわらず)?Seqscalascala.collectionSeq
  2. コレクションを初期化してから凍結するための標準的なメカニズムは何ですか(Java では でラップすることによって実現されますunmodifiable)。
  3. 一部のコレクション型 ( などMultiMap) が変更可能としてのみ定義されているのはなぜですか? (不変はありませんMultiMap)?

Daniel Spiewak のscala コレクションに関する優れたシリーズを読んだことがありますが、実際にそれらを実際にどのように使用するかについてはまだ戸惑っています。以下は、完全なパッケージ宣言が強制されているため、少し扱いに​​くいようです。

class MyScala {
  var mySet: scala.collection.Set[String] = null 

  def init(): Unit = {
     val s = scala.collection.mutable.Set.empty[String]
     s + "Hello"
     s + "World"
     mySet = scala.collection.immutable.Set(s : _ *)

  }
}

不変コレクションは変更できないため (Java の場合と同様に、ラッパーの下で基礎となるコレクションを変更することができます) 、これは Java バージョンよりも間違いなく正しいと言えます。unmodifiable

4

4 に答える 4

26

List と Seq が scala.collection ではなくパッケージ scala で定義されているのはなぜですか (Seq の実装はコレクションのサブパッケージに含まれていますが)。

それらは一般的に非常に有用であると見なされているため、scala.Predef のシノニムを介してすべてのプログラムに自動的にインポートされます。

コレクションを初期化してから凍結するための標準的なメカニズムは何ですか?

Java には、コレクションを凍結するメカニズムがありません。例外をスローするラッパーで(まだ変更可能な)コレクションをラップするためのイディオムしかありません。Scala での適切なイディオムは、可変コレクションを不変コレクションにコピーすることです。おそらく :_* を使用します。

一部のコレクション タイプ (MultiMap など) が変更可能としてのみ定義されているのはなぜですか? (不変の MultiMap はありません)?

チーム/コミュニティはまだそこに到達していません。2.7 ブランチでは多くの追加が行われ、2.8 ではさらに多くの追加が予定されています。

以下は、完全なパッケージ宣言が強制されているため、少し扱いに​​くいようです。

Scala ではインポート エイリアスが許可されているため、この点に関して常に Java よりも冗長ではありません (たとえば、java.util.Date と java.sql.Date を参照してください。両方を使用すると、一方が完全修飾されます)。

import scala.collection.{Set => ISet}
import scala.collection.mutable.{Set => MSet}

class MyScala {
  var mySet: ISet[String] = null 

  def init(): Unit = {
     val s = MSet.empty[String]
     s + "Hello"
     s + "World"
     mySet = Set(s : _ *)
  }
}

もちろん、実際には init asdef init() { mySet = Set("Hello", "World")}を記述してすべての問題を解決するか、コンストラクターに入れるだけで済みます。var mySet : ISet[String] = Set("Hello", "World")

于 2009-03-23T22:21:57.713 に答える
7

可変コレクションは時々役に立ちます (ただし、常に不変コレクションを最初に確認する必要があることに同意します)。それらを使用する場合、私は書く傾向があります

import scala.collection.mutable

ファイルの先頭に、(たとえば):

val cache = new mutable.HashMap[String, Int]

私のコードで。つまり、scala.collection.mutable.HashMap ではなく、mutable.HashMap と書くだけでよいということです。上記のコメンテーターが言及したように、インポートで名前を再マップできます (例: “import scala.collection.mutable.{HashMap => MMap}”)。

  1. 使用しているクラスがより明確になるように、名前を混乱させないことを好みます。
  2. ソースに「mutable.ClassName」を含めることが過度の負担にならないように、「mutable」を使用することはめったにありません。

(また、'avoid nulls' コメントもエコーできますか。これにより、コードがより堅牢で理解しやすくなります。また、皆さんが期待するほど Option を使用する必要さえないことがわかりました。)

于 2009-11-19T12:40:34.010 に答える
4

いくつかのランダムな考え:

  1. 私は決して使用しませんnull、私は使用しますOptionが、それはまともなエラーを投げます。この慣習により、多くの機会が取り除かれ、人々はまともなエラーを書くことを余儀なくされました NullPointerException
  2. 本当に必要でない限り、「変更可能な」ものを調べないようにしてください。

したがって、後でセットを初期化する必要がある scala の例に対する私の基本的な考え方は次のとおりです。

class MyScala {
  private var lateBoundSet:Option[ Set[ String ] ] = None
  def mySet = lateBoundSet.getOrElse( error("You didn't call init!") )

  def init {
     lateBoundSet = Some( Set( "Hello", "World" ) )
  }
}

私は最近、オフィスの周りで涙を流しています。「ヌルは悪だ!」

于 2009-06-05T21:16:32.097 に答える
3

現在のバージョンのScalaコレクションAPIにはいくつかの矛盾がある可能性があることに注意してください。Scala 2.8(2009年後半にリリース予定)では、コレクションAPIがオーバーホールされ、一貫性と柔軟性が向上しています。

ScalaのWebサイトでこの記事を参照してください:http ://www.scala-lang.org/node/2060

lateBoundSetを使用してTristanJuricekの例に追加するには、次のようにします。Scalaには、「lazy」キーワードを使用したレイジー初期化のメカニズムが組み込まれています。

class MyClass {
    lazy val mySet = Set("Hello", "World")
}

これにより、mySetは、新しいMyClassインスタンスを作成するときにすぐにではなく、最初の使用時に初期化されます。

于 2009-08-03T11:25:52.917 に答える