5

リスト内の各文字列の頻度をカウントし、結果を可変マップに格納する次のコードについて考えてみます。これはうまく機能しますが、+ =メソッドがどこで定義されているのかわかりませんか?!これは奇妙な暗黙の変換のことですか、それとも何ですか?このコードはどこかで見ましたが、+=の説明が含まれていませんでした。

val list = List("a", "b", "a")
val counts = new scala.collection.mutable.HashMap[String, Int]().withDefaultValue(0)
list.foreach(counts(_) += 1)
counts
//> res7: scala.collection.mutable.Map[String,Int] = Map(a -> 2, b -> 1)

mapを適用するとIntが返されますが、Intには+ =がなく、このメソッドはマップを新しい値で更新するため、applyが+=メソッドを持つ可変整数を返すように見えます...

4

2 に答える 2

8

これは暗黙の変換ではなく、脱糖です。書き込み:

x += 1

脱糖剤:

x = x + 1

のクラスにメソッドが定義されてxいない場合。+=

同じやり方で:

counts("a") += 1

脱糖剤:

counts("a") = counts("a") + 1

counts("a")は、Intであり、メソッドが定義されIntていないためです。+=

一方、次のように記述します。

x(expression1) = expression2

Scalaのメソッドの呼び出しへの脱糖update

x.update(expression1, expression2)

すべてのミュータブルMapにはupdateメソッドが定義されています。これにより、マップにキーを設定できます。

したがって、式全体は次のように脱糖されます。

list.foreach(x => counts.update(x, counts(x) + 1))

これをScalaのsのメソッド+=と混同しないでください。このメソッドは、そのキーがすでに存在する場合はマップ内のエントリを更新するか、新しいキーと値のペアを追加します。参照、つまり同じマップを返すため、呼び出しを連鎖させることができます。ScalaDocまたはソースコードを参照してください。+=mutable.Mapthis+=

于 2013-01-30T13:30:27.997 に答える
3

コードの一部でどのコンパイラの魔法が起こっているのか疑問に思うこれらの瞬間にscalac -printは、あなたの親友です(この質問を参照してください)。

scalac -print C.scalaC.scalaがどこにあるかを行う場合

package test

class C {
    def myMethod() {
        val counts = new scala.collection.mutable.HashMap[String, Int]().withDefaultValue(0)
        counts("a") += 1
    }
}

あなたが得る

package test {
  class C extends Object {
    def myMethod(): Unit = {
      val counts: collection.mutable.Map = new collection.mutable.HashMap().withDefaultValue(scala.Int.box(0));
      counts.update("a", scala.Int.box(scala.Int.unbox(counts.apply("a")).+(1)))
    };
    def <init>(): test.C = {
      C.super.<init>();
      ()
    }
  }

私にとっても驚きでしたが、どうやらscalacが変身するようです

map(key) =<op> rhs

map.update(key, map.apply(key) <op> rhs)
于 2013-01-30T13:36:52.950 に答える