サーチ…


備考

値と変数の名前は、より低いラクダの場合にする必要があります

定数の名前はラクダの大文字にする必要があります。つまり、メンバがfinalで不変で、パッケージオブジェクトまたはオブジェクトに属している場合は、定数と見なすことができます

メソッド、値、変数名は、ラクダの方が小さい

出典: http : //docs.scala-lang.org/style/naming-conventions.html

このコンパイル:

val (a,b) = (1,2)
// a: Int = 1
// b: Int = 2

しかしこれはしません:

val (A,B) = (1,2)
// error: not found: value A
// error: not found: value B

valとvarだけではありません

valvar

scala> val a = 123
a: Int = 123

scala> a = 456
<console>:8: error: reassignment to val
       a = 456

scala> var b = 123
b: Int = 123

scala> b = 321
b: Int = 321
  • val参照は変更できません: Java final変数のように、初期化されたら変更できません
  • varリファレンスは、Javaでの単純な変数宣言として再割り当て可能です

不変および変更可能なコレクション

  val mut = scala.collection.mutable.Map.empty[String, Int]
  mut += ("123" -> 123)
  mut += ("456" -> 456)
  mut += ("789" -> 789)

  val imm = scala.collection.immutable.Map.empty[String, Int]
  imm + ("123" -> 123)
  imm + ("456" -> 456)
  imm + ("789" -> 789)

  scala> mut
    Map(123 -> 123, 456 -> 456, 789 -> 789)

  scala> imm
    Map()

scala> imm + ("123" -> 123) + ("456" -> 456) + ("789" -> 789)
    Map(123 -> 123, 456 -> 456, 789 -> 789)

Scalaの標準ライブラリは、不変のデータ構造と変更可能なデータ構造の両方を提供します。不変のデータ構造が「変更」されるたびに、元のコレクションをインプレースで変更する代わりに、新しいインスタンスが生成されます。コレクションの各インスタンスは、別のインスタンスと重要な構造を共有することができます。

変更可能で不変なコレクション(Scalaの公式文書)

しかし、私はこの場合に不変性を使用することはできません!

のは、一例として、2取る関数ピックアップしてみましょうMapと戻りMapのすべての要素含むmamb

def merge2Maps(ma: Map[String, Int], mb: Map[String, Int]): Map[String, Int]

最初の試みは、 for ((k, v) <- map)を使ってマップの要素を反復し、何らかの方法でマージされたマップを返すことができます。

def merge2Maps(ma: ..., mb: ...): Map[String, Int] = {

  for ((k, v) <- mb) {
    ???
  }

}

この非常に最初の動きはすぐに制約を追加します。 その外の突然変異for必要とされています 。これは、以下をfor場合にはより明確for

// this:
for ((k, v) <- map) { ??? }

// is equivalent to:
map.foreach { case (k, v) => ??? }

なぜ我々は突然変異を起こさなければならないのか?

foreachは副作用に頼っています。私たちがforeach内で何か起こることを望むたびに、 "副作用"が必要です。この場合、変数var resultを変更するか、変更可能なデータ構造を使用することができます。

resultマップの作成と塗りつぶし

のは、仮定しようmambしているscala.collection.immutable.Map 、私たちが作成することができresultから地図をma

val result = mutable.Map() ++ ma

次に、要素を追加するmbを繰り返し、 maの現在の要素のkeyがすでに存在する場合は、 mb要素で上書きします。

mb.foreach { case (k, v) => result += (k -> v) }

変更可能な実装

これまでのところ非常にうまくいきました。「変更可能なコレクションを使用する必要があります。

def merge2Maps(ma: Map[String, Int], mb: Map[String, Int]): Map[String, Int] = {
  val result = scala.collection.mutable.Map() ++ ma
  mb.foreach { case (k, v) => result += (k -> v) }
  result.toMap // to get back an immutable Map
}

予想通り:

scala> merge2Maps(Map("a" -> 11, "b" -> 12), Map("b" -> 22, "c" -> 23))
  Map(a -> 11, b -> 22, c -> 23)

レスキューへの折り畳み

このシナリオでforeachを取り除くにはどうすればよいですか?基本的には、コレクション要素を繰り返し処理して関数を適用する一方、オプションの結果を累積するには.foldLeftを使用することができます。

def merge2Maps(ma: Map[String, Int], mb: Map[String, Int]): Map[String, Int] = {
  mb.foldLeft(ma) { case (result, (k, v)) => result + (k -> v) }
  // or more concisely mb.foldLeft(ma) { _ + _ }
}

この場合、私たちの "結果"は、 .foldLeft zeroであるmaから始まる累積値.foldLeft

中間結果

明らかに、この不変の解決策は、折りたたみ中に多くのMapインスタンスを生成して破壊していますが、それらのインスタンスはMap完全なクローンではなく、既存のインスタンスと重要な構造(データ)を共有していることに言及する価値があります。

より簡単な合理性

.foldLeftアプローチのように宣言的であれば、意味論を.foldLeftする方が簡単です。不変のデータ構造を使用することで、実装の理解が容易になります。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow