0

次の2つが同等ではないScalaの奇妙な機能に出くわしました。

var map = Map[A,B]() 
map += ( key -> (valueGen(key)))

と同じ結果は得られません

var map = Map[A,B]() 
val result = valueGen(key)
map += ( key -> result)

2 番目のスニペットは期待どおりに機能しますが、最初のスニペットはマップに正しく追加されません。代わりに、前の値を上書きして、追加されたすべての値ではなく、最後に書き込まれた値のみがマップに含まれるようにします。

4

2 に答える 2

3

valueGenこれは以前に見たことがありますが、関数とこのコードが一緒に再帰的である場合にのみ問題が発生します。これは、括弧内の式が最初に実行されることが保証されていないためだと思います。括弧は演算子のみをバインドします。Scala はマップ上の += を次のように解釈する必要があります。

map = map + (expression)

を実行するmap + (expression)と、最初にマップ オペランドをプラス演算子に読み取り、それを保持します。次に、 を評価しようとし(expression)ます。(expression)関数への呼び出しが含まれている場合は、呼び出しを行い、この特定の呼び出しからキャッシュされたマップvalueGenに追加します。への呼び出しが再帰的にこの関数を呼び出して終了した場合 (そして最初にマップを変更した場合)、この呼び出しからキャッシュされたバージョン + 結果でそれらの変更が上書きされます。そのため、関数が再帰的である場合は、+= 演算子とは別に関数を呼び出す必要があります。valueGenvalueGen

于 2012-05-31T05:13:06.973 に答える
1

私が走るとき

object test {
    def main(args: Array[String]) {
        var map = Map[String,Int]()
        map += ("hello" -> (valueGen("hello")))
        map += ("bye" -> (valueGen("bye")))
        println(map)
    }

    def valueGen(x: String) = x.length
}

私は得る

Map(hello -> 5, bye -> 3)

あなたが見ているものの実行可能な例を提供できますか?

于 2012-05-31T05:11:37.293 に答える