Question

The following code:

var m: Map[String, Int] = Map("A" -> 1, "BB" -> 2, "CCC" -> 3)

m = m filterKeys { s => s.length < 3 }

Does not compile. I get the following error:

error: type mismatch
found: collection.this.Map.Projection[scala.this.Predef.String,scala.this.Int]
required: collection.this.Map[scala.this.Predef.String,scala.this.Int]
m = m filterKeys { s => s.length < 3 }

I don't really understand this as according to the scaladoc a Projection[A,B] extends the trait Map[A,B+]. That is, a Projection is a Map.

I thought it might be something to do with the contravariant type B but if I use Any instead of Int, it still doesn't compile. What am I missing? The solution is to do:

var m: Map[String, Int] = Map("A" -> 1, "BB" -> 2, "CCC" -> 3)

m = Map(m filterKeys { s => s.length < 3 } toSeq : _ *) 

but this seems inelegant to me.

Was it helpful?

Solution

OK - this has been figured out with the help of the scala console:

scala> var m = Map("A" -> 1, "BB" -> 2, "CCC" -> 3)
m: scala.collection.immutable.Map[java.lang.String,Int] = Map(A -> 1, BB -> 2, CCC -> 3)

So the type inference is inferring m's type as being an immutable map. The following code will compile OK:

var m: collection.Map[String, Int] = Map("A" -> 1, "BB" -> 2, "CCC" -> 3)
m = m filterKeys { s => s.length < 3 }

However, this is not much help as the map can not be added to in such a way as to return a collection.Map. I think that they should have overridden the ++ method inherited from Iterable with Map as the return type.

Could anyone comment on this? What use a collection.Map?

OTHER TIPS

I'm curious why you want m to be var rather than val - if you're not trying to reassign the Map to itself, things seem to work OK, as shown in the repl, and this is more in keeping with the scala philosophy of preferring immutability where possible:

scala> val m = Map("A" -> 1, "BB" -> 2, "CCC" -> 3) 
m: scala.collection.immutable.Map[java.lang.String,Int] = Map((A,1), (BB,2), (CCC,3))

scala> val n = m filterKeys { s => s.length < 3 }
n: scala.collection.immutable.Map[java.lang.String,Int] = Map((A,1), (BB,2))

I see that the question is kind of old, it's possible that the behaviour you're seeing is different in Scala 2.8 given the major refactoring of the collections classes.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top