Uncontrolled type warning in Scala?

Suppose I have a map m: Map[Any, Int] . Now I would like to take only the records (String, Int) from m and create a new map m1: Map[String, Int] with these records.

I am trying to do the following:

 val m1: Map[String, Int] = m collect {case e:(String, Int) => e} 

It seems to work, but I get a warning: non variable type-argument The string in the type template (String, Int) is not marked, because it is deleted by erasing.

How can I get rid of the warning?

+6
source share
3 answers

you probably want:

 val m1: Map[String, Int] = m collect {case (k:String, v:Int) => k->v} 
+9
source

(For reference only. What do you want a virtual answer .)

 val m1: Map[String, Int] = m flatMap { e => e._1 match { case e1: String => Some(e1 -> e._2) case _ => None } } 
+3
source

Thorough testing will show that your solution actually matches everything on the map, and not just records like (String, Int). A warning from the compiler tells you that the types of your match will be thrown out at runtime so that your code actually does something like this:

val m1: Map[String, Int] = m collect {case e:Tuple2[Any,Any] => e.asInstanceOf[Tuple2[String,Int]]}

And the call to asInstanceOf will not explode, since it only discards Tuple2, and the bit (String, Int) is again lost due to erasure. You will get an unpleasant crash when you try to repeat the result, though ...

Try it in REPL

  val m:Map[String,Int] = Map("2" -> 3, 3 -> 4, "6" -> 10) collect {case e:(String, Int) => e} // Oops, thought we would get '2' m size // Nothing wrong with this code except m contains some // hidden nasties which causes us to blow up for ((s:String, i:Int) <- m) yield s.length + i 

`

+2
source

Source: https://habr.com/ru/post/914035/


All Articles