Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

what does += operation really do in scala map?

Tags:

scala

As the code shows:

val map = scala.collection.mutable.Map[Int, Int]().withDefaultValue(0)
println(map(1))
map(1) = 10
println(map(1))
map(1) += 10
println(map(1))

and the output:

0
10
20

However, in my opinion, "map(1) += 10" is invalid as in java, and even valid, the result after this line, map(1) should be 10.

So Why??? and what exactly operation "+=" do in map ??

like image 884
CodeBoy Avatar asked Jan 06 '23 23:01

CodeBoy


2 Answers

First, += is an assignment operator, because it ends in = and isn't a comparison operator. This means that if there is no suitable method (and Int doesn't have a += method), map(1) += 10 is converted to map(1) = map(1) + 10. By the rules in Assignments, this becomes map.update(1, map(1) + 10) and this becomes map.update(1, map.apply(1) + 10) because map is an object rather than a method.

like image 146
Alexey Romanov Avatar answered Jan 14 '23 20:01

Alexey Romanov


The question asked 'what exactly operation "+=" do in map ??' is not relevant to the situation you described. Map's method += adds entry (key -> value) to Map, so that map(key) == value.

So the question is: what does map(1) += 10 does.

This simple lines

  map(1) += 10

compiles into this javacode

  24: invokestatic  #36                 // Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
  27: aload_2
  28: iconst_1
  29: invokestatic  #36                 // Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
  32: invokeinterface #43,  2           // InterfaceMethod scala/collection/mutable/Map.apply:(Ljava/lang/Object;)Ljava/lang/Object;
  37: invokestatic  #47                 // Method scala/runtime/BoxesRunTime.unboxToInt:(Ljava/lang/Object;)I
  40: bipush        10
  42: iadd
  43: invokestatic  #36                 // Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
  46: invokeinterface #51,  3           // InterfaceMethod scala/collection/mutable/Map.update:(Ljava/lang/Object;Ljava/lang/Object;)V

Remove boxing and unboxing ops - we are not interested in them(line 24, 29, 37, 43). Review the rest:

We get value that was in map

  27: aload_2
  28: iconst_1
  32: invokeinterface #43,  2           // InterfaceMethod scala/collection/mutable/Map.apply:(Ljava/lang/Object;)Ljava/lang/Object;

Add 10 to it:

  40: bipush        10
  42: iadd

And accomplish update:

  46: invokeinterface #51,  3           // InterfaceMethod scala/collection/mutable/Map.update:(Ljava/lang/Object;Ljava/lang/Object;)V

Seems map(1) += 10 is desugared to map.update(1, map.apply(1) + 10)

like image 35
nikiforo Avatar answered Jan 14 '23 18:01

nikiforo