14

Odersky et alのScalaの本では、彼らは使用リストを言っています。私はカバーする本の表紙を読んでいませんが、すべての例はvalListを使用しているようです。私が理解しているように、varsではなくvalsを使用することもお勧めします。しかし、ほとんどのアプリケーションでは、varListとvalMutableListのどちらを使用するかというトレードオフはありませんか?明らかに、可能な場合はvalリストを使用します。しかし、多くのvarリスト(またはvar Vectorsなど)を使用するのは良い習慣ですか?

私はC#から来たScalaにかなり慣れていません。そこに私はたくさんありました:

public List<T> myList {get; private set;}

C#に不変性が組み込まれている場合は、valsとして簡単に宣言できたコレクション。これは、コレクションの存続期間中に要素がコレクションに追加および削除されたとしても、コレクション自体は構築後に変更されないためです。したがって、varコレクションを宣言することは、不変性から一歩離れたように感じます。

回答とコメントに応えて、Scalaの大きなセールスポイントの1つは、LispやHaskellの場合のように、コードの記述方法を完全に変更することなく、多くの利点を得ることができるということです。

4

5 に答える 5

17

たくさんのvarリスト(またはvarVectorsなど)を使用するのは良い習慣ですか?

var可変コレクションで使用するよりも、不変コレクションで使用する方が良い方法だと思いvalます。頭のてっぺんから

  • 動作についてより多くの保証があります。オブジェクトに可変リストがある場合、他の外部オブジェクトがそれを更新するかどうかはわかりません。

  • 可変性の範囲を制限します。コレクションを返すメソッドは不変のものを生成するため、1つのオブジェクト内でのみ可変性があります

  • varをvalに割り当てるだけで不変化するのは簡単ですが、可変コレクションを不変にするには、別のコレクションタイプを使用して再構築する必要があります。

広範なI/Oを使用する時間依存のアプリケーションなど、状況によっては、最も簡単な解決策は可変状態を使用することです。また、状況によっては、変更可能なソリューションの方がエレガントです。ただし、ほとんどのコードでは、可変性はまったく必要ありません。重要なのは、ループの代わりに高階関数のコレクションを使用することです。適切な関数が存在しない場合は再帰を使用します。これは思ったより簡単です。List(およびほとんど同じである他のコレクション)のメソッドを理解するために少し時間を費やす必要があります。最も重要なものは次のとおりです。

map:指定した関数をコレクション内の各要素に適用します-配列内の値をループして更新する代わりに使用します

foldLeft:コレクションから単一の結果を返します-アキュムレータ変数をループして更新する代わりに使用します

for-yield式:特にネストされたループタイプの問題の場合は、マッピングとフィルタリングを簡素化します

最終的に、関数型プログラミングの多くは不変性の結果であり、実際には一方を他方なしで持つことはできません。ただし、ローカル変数は主に実装の詳細です。ローカルスコープから脱出できない限り、多少の可変性に問題はありません。したがって、ローカル変数はエクスポートされるものではないため、不変のコレクションを持つ変数を使用してください。

于 2012-06-12T18:09:34.157 に答える
8

Listあなたは、が可変でなければならないか、それを指しているものはすべて可変でなければならないと仮定しています。つまり、以下の2つの選択肢のいずれかを選択する必要があります。

val list: collection.mutable.LinkedList[T]
var list: List[T]

それは誤った二分法です。あなたは両方を持つことができます:

val list: List[T]

だから、あなたが尋ねるべき質問は、私がそれをどのように行うのかということです。、しかし、私たちはあなたがそれを試して特定の問題に直面したときにのみそれに答えることができます。すべての問題を解決する一般的な答えはありません(まあ、モナドと再帰がありますが、それは一般的すぎます)。

だから...試してみてください。ほとんどのScalaの質問が、コードをより機能的にする方法に正確に関係しているコードレビューに興味があるかもしれません。しかし、最終的には、それを実行するための最良の方法は、試してみて、特定の問題を理解できない場合はStackOverflowに頼ることだと思います。

于 2012-06-12T15:12:07.890 に答える
1

これが、関数型プログラミングにおけるこの可変性の問題の見方です。

最良の解決策:値が最良であるため、関数型プログラミングの使用法で最良のものは値と再帰関数です。

val myList = func(4); 
def func(n) = if (n>0) n::func(n) else Nil

可変のものが必要:可変のものが必要な場合や、すべてが非常に簡単になる場合があります。この状況に直面したときの私の印象は、可変構造を使用することです。val list: collection.mutable.LinkedList[T]代わりにを使用するのはvar list: List[T]、パフォーマンスが実際に向上したためではなく、可変コレクションですでに定義されている可変関数のためです。

このアドバイスは個人的なものであり、パフォーマンスが必要な場合はお勧めできませんが、Scalaでの日常のプログラミングに使用するガイドラインです。

于 2012-06-12T16:13:28.687 に答える
1

val可変/不変の問題をvar特定のユースケースから切り離すことはできないと思います。少し深くさせてください。自分自身に尋ねたい2つの質問があります。

  1. コレクションを外部に公開するにはどうすればよいですか?
    1. 現在の状態のスナップショットが必要です。コレクションをホストしているエンティティに加えられた変更に関係なく、このスナップショットは変更されません。このような場合、不変を優先する必要がありますvar。その理由は、ミュータブルを使用してこれを行う唯一の方法valは、防御コピーを使用することであるためです。
    2. 元のオブジェクトの状態への変更を反映するために変更する必要がある状態のビューが必要です。この場合、不変を選択しval、変更不可能なラッパーでラップして返す必要があります(Javaの場合と同様Collections.unmodifiableList()、Scalaでその方法を尋ねられる質問があります)。不変の変数でこれを達成する方法がわからないので、ここでの選択は必須だと思います。
    3. 私は副作用がないことだけを気にします。この場合、2つのアプローチは非常に似ています。不変varを使用すると、内部表現を直接返すことができるため、おそらく少し明確になります。
  2. コレクションをどのように変更しますか?
    1. 私は通常、一括変更を行います。つまり、コレクション全体を一度に設定します。これにより、不変varがより適切な選択になります。入力内容を現在の状態に割り当てるだけで、すでに問題はありません。不変valの場合、最初にコレクションをクリアしてから、新しいコンテンツをコピーする必要があります。さらに悪いことになります。
    2. 私は通常、ポイントごとに変更を加えます。つまり、コレクションに1つの要素(またはいくつかの要素)を追加/削除します。これは私が実際にほとんどの時間見ているものであり、コレクションは単なる実装の詳細であり、traitそのステータスをポイントごとに操作するための唯一の公開メソッドです。この場合、一般的にミュータブルの方がパフォーマンスの面で優れている可能性がありますが、これが問題になる場合は、 Scalaのコレクションのパフォーマンスvalを確認することをお勧めします。
于 2017-03-27T09:27:10.373 に答える
0

varリストを使用する必要がある場合は、どうしてですか?問題を回避するために、たとえば変数のスコープを制限することができます。しばらく前に同様の質問があり、かなり良い答えがありました。valとvarをいつ使用するかというscalaの可変および不変のセットです。

于 2012-06-12T15:13:14.130 に答える