How to dynamically cast a variable to Option

474 views Asked by At

I'd like to cast variables dynamically to Option[T]. The semantic is: if variable x matches T type, then cast should return Some(x) and it should return None otherwise. Using single map invocation is much cleaner than using isInstanceOf[T] accompanying asInstanceOf[T] or building monstrous case switches.

I had tried simple code below

object OptionCast {
  def apply[T](source : Any) : Option[T] = source match {
    case s : T => Some(s)
    case _ => None
  }
}

but it ignores types actually: OptionCast[Int]("some").map(_ + 2) gives me type error.

How should I rewrite this code?

1

There are 1 answers

0
Daniel C. Sobral On

The problem with your code is that T is erased -- methods in bytecode do not have type parameters, so T is erased to Object and, therefore, true for everything.

This works, with some limitations:

import scala.reflect.ClassTag
object OptionCast {
  def apply[T : ClassTag](source : Any) : Option[T] = source match {
    case s : T => Some(s)
    case _ => None
  }
}

There are two important limitations here:

  1. It cannot check type parameters, because type parameters are erased are runtime. That means you can call OptionCast.apply[List[Int]](List("a")) and it will return Some(List("a")). To get around that, you have to get around type erasure.
  2. Any AnyVal class will be boxed, so you have to check against java.lang.Integer to catch Int, and so on.