I am perplexed why I cannot yield a collection from the following line of Scala code:
val pairs = for( v <- vc; o <- oc) yield (v,o)
It's inside of this function, which is using immutable Vectors.
private def recMergeVirtualAndReal(mCell: RCell, vc: Vector[Cell], oc: Vector[Cell]): Vector[Cell] = {
var temp_oc = oc
val pairs = for( v <- vc; o <- oc) yield (v,o)
val newVCells =
for((left, right) <- pairs if left contains right) yield {
temp_oc = temp_oc.filterNot(o => o == left || o == right)
captureVCells(left,right,mCell)
}
if(newVCells.nonEmpty) recMergeVirtualAndReal(mCell, recMergeVirtualCells(newVCells ++ vc), temp_oc)
else vc
}
I get the following error in the stack trace:
Exception in thread "main" java.lang.ClassCastException: scala.collection.immutable.Vector cannot be cast to game.Cell
at model.Board$$anonfun$10.apply(Board.scala:223)
at scala.collection.immutable.List.flatMap(List.scala:327)
I'm confused because I am not trying to cast anything, its just a simple statement without any type conversions.
I also tried this in case the compiler couldn't understand the types:
val pairs = for( v: Cell <- vc: Vector[Cell]; o: Cell <- oc: Vector[Cell]) yield (v: Cell,o: Cell)
You are probably doing an unsafe cast somewhere in the calling code. Check the arguments to your function, and check especially for uses of asInstanceOf
.
Here's an example of how an unsafe cast could cause this problem. First, we create a List[Int]
, then force the compiler to think of it as a List[String]
.
val ls = List(1).asInstanceOf[List[String]]
This works, as the Scala compiler is okay with it, and the generics are unchecked at runtime until we try to store an element of the list to a variable:
val x = ls.head // java.lang.ClassCastException: java.base/java.lang.Integer cannot be cast to java.base/java.lang.String
Probably, somewhere else in your code, you are calling .asInstanceOf[Vector[Cell]]
on a Vector[Vector[Something]]
, then passing it to this function. Never use asInstanceOf
if you can help it.