tags:

views:

136

answers:

1

I would like to create a Map type so something like the below is possible:

VariantMap(1) = "Test"
VariantMap("a") = 42

and VariantMap("a") would have a type of Option[Int]. Here is the code I have so far which results in Option[Nothing]:

object VariantMap {
  import scala.reflect.Manifest

  private var _map= Map.empty[Any,(Manifest[_], Any)] 

  def update[T](name: Any, item: T)(implicit m: Manifest[T]) {
    _map = _map(name) = (m, item)
  }

  def apply[T](key:Any)(implicit m : Manifest[T]) = {
    val o = _map.get(key)

    o match {
      case Some((om: Manifest[_], s : Any)) => Some[T](s.asInstanceOf[T])
      case _ => None
    }
  }
}

I'm new to scala so I apologize if I am missing something obvious.

+2  A: 

I'm not sure whether it is directly possible to do what you want. The apply method takes a type parameter [T], but if you don't specify it, the compiler doesn't know what type T exactly represents. In this case it infers Nothing, the subtype of any other type.

Using your code, supplying a type parameter gives the following result:


scala> VariantMap[Int]("a")
res0: Option[Int] = Some(1)

scala> VariantMap[String]("a")
res1: Option[String] = Some(1)

So now, any type is ok, not exactly perfect either. You can slightly improve on it with the following variation:


object VariantMap {
   import scala.reflect.Manifest

   private var _map= Map.empty[Any,(Manifest[_], Any)] 

   def update[T](name: Any, item: T)(implicit m: Manifest[T]) {
      _map = _map(name) = (m, item)
   }

   def apply[T](key:Any)(implicit m : Manifest[T]): Option[T] = {
     val o = _map.get(key)      
     o match {
       case Some((om: Manifest[_], s : Any)) => if (om  None
     }
  }
}

scala> VariantMap("a")
res0: Option[Nothing] = None

scala> VariantMap[Int]("a")
res1: Option[Int] = Some(1)

scala> VariantMap[String]("a")
res2: Option[String] = None

Which probably is also not really what you wanted (this just a type safe map), but I don't really see a better solution at this moment.

Arjan Blokzijl