Reputation: 848
I have created an immutable list and try to fold it to a map, where each element is mapped to a constant string "abc". I do it for practice. While I do that, I am getting an error. I am not sure why the map (here, e1 which has mutable map type) is converted to Any.
val l = collection.immutable.List(1,2,3,4)
l.fold (collection.mutable.Map[Int,String]()) ( (e1,e2) => e1 += (e2,"abc") )
l.fold (collection.mutable.Map[Int,String]()) ( (e1,e2) => e1 += (e2,"abc") )
<console>:13: error: value += is not a member of Any
Expression does not convert to assignment because receiver is not assignable.
l.fold (collection.mutable.Map[Int,String]()) ( (e1,e2) => e1 += (e2,"abc") )
Upvotes: 0
Views: 368
Reputation: 44908
At least three different problem sources here:
Map[...]
is not a supertype of Int
, so you probably want foldLeft
, not fold
(the fold
acts more like the "banana brackets", it expects the first argument to act like some kind of "zero", and the binary operation as some kind of "addition" - this does not apply to mutable maps and integers).fold
and foldLeft
. In this case, you probably want to return the modified map. This is why you need ; m
(last expression is what gets returned from the closure).m += (k, v)
is not what you think it is. It attempts to invoke a method +=
with two separate arguments. What you need is to invoke it with a single pair. Try m += ((k, v))
instead (yes, those problems with arity are annoying).Putting it all together:
l.foldLeft(collection.mutable.Map[Int, String]()){ (m, e) => m += ((e, "abc")); m }
But since you are using a mutable map anyway:
val l = (1 to 4).toList
val m = collection.mutable.Map[Int, String]()
for (e <- l) m(e) = "abc"
This looks arguably clearer to me, to be honest. In a foldLeft
, I wouldn't expect the map to be mutated.
Upvotes: 3
Reputation: 1371
Folding is all about combining a sequence of input elements into a single output element. The output and input elements should have the same types in Scala. Here is the definition of fold
:
def fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1
In your case type A1
is Int
, but output element (sum type) is mutable.Map
. So if you want to build a Map
throug iteration, then you can use foldLeft
or any other alternatives where you can use different input and output types. Here is the definition of foldLeft
:
def foldLeft[B](z: B)(op: (B, A) => B): B
Solution:
val l = collection.immutable.List(1, 2, 3, 4)
l.foldLeft(collection.immutable.Map.empty[Int, String]) { (e1, e2) =>
e1 + (e2 -> "abc")
}
Note: I'm not using a mutabe Map
Upvotes: 2