11 Oct 2009

Goddamn you Type Erasure.

Look at this (Scala) code and tell me what's wrong here:

 

class H{};
var a = List[Option[Any]]();
a: List[Option[Any]] = List();
a = Some(new H)::a;
a: List[Option[Any]] = List(Some(H@44af17c7))
a = Some(7)::a;
a: List[Option[Any]] = List(Some(7),Some(H@44af17c7))
def get[T](id:Int):Option[T] = {
     a(id) match {
         case None => None;
         case Some(x) => {
             try{Some(t.asInstanceOf[T]);}
             catch{case _ => None;}
         }
     }
 }
get_from: [T](Int)Option[T] get_from[H](0);
res1: Option[H] = Some(7)

 

Because I was using abstract types, the try always succeeds. If I were to replace:

 

def get[T](id:Int):Option[T] = {
     a(id) match {
         case None => None;
         case Some(x) => {
             try{Some(t.asInstanceOf[T]);}
             catch{case _ => None;}
         }
     }
 }

 

with:

 

def get(id:Int):Option[H] = {
     a(id) match {
         case None => None;
         case Some(x) => {
             try{Some(x.asInstanceOf[H]);}
             catch{case _=> None;}
         }
     }
 }

 

Then the try would fail on get(0) and return None. God-fucking-dammit.

Gotta love that JVM.