object Helper {
case class IsMap(x: Map[String,Any])
case class IsT[T](t: T)
implicit class MapFunctions(val map: Map[String,Any]) {
def path[T](path : String*) : Option[T] = {
if(path.size == 1)
None
map.get(path.head).get match {
case IsMap(item) => item.path(path.tail:_*)
case IsT(item) => Option(item)
case _ => throw new Exception("Unexpected type encountered in path")
}
}
}
}
I'm still quite new to Scala. I want to to avoid Option(item.asInstanceOf[T]) in the IsT(item) portion of the pattern matching. I am using case classes to pattern match against parameterized types to stop the type erasure. What I want to do is be able to have IsT(item) match only if item is of type T. Running this code doesn't seem to match on it. What am I doing wrong?
Update: Up until tonight, I thought Scala had magically solved some of the nastier problems with type erasure that Java had. I knew there were still times when type erasure was present but I didn't realize it suffered pretty much the same. I played with the TypeTag a little bit. I was excited by the type interference in Scala and the ability to have it infer the type that I was trying to return but having val myType = path("blah", "blah").get screwed this up because the inferred type is Nothing which would cause a casting error. I ended up solving this the same way I had to solve it in java- have the path() method take Class[T] and use that as the parameterized return type. It's unfortunate... somehow I thought Scala was capable of so much more...
Anyways- my new method looks like this:
object Helper {
implicit class MapFunctions[K,V](val map: Map[K,V]) {
def path[T<:V](clazz: Class[T], pathParts: K*): Option[T] = {
if (pathParts.size == 0)
None
else {
map.get(pathParts.head).get match {
case im: Map[K, V] if pathParts.size > 1 => im.path(clazz, pathParts.tail: _*)
case i => Option(i.asInstanceOf[T])
}
}
}
}
}
Oh... and the purpose of this implicit? My team has spent the better part of a week trying to find a good json library in Scala. We've used json4s previously but aren't happy with the fact that it's container object stores a List of Tuple2 instead of a map and we're heaving on access so this isn't going to work for us. We've reverted to using Jackson and just having it deserialize the json to Map[String,Any]. I found myself doing things where I wanted to cascade down the map like a tree into nested objects and this "path" method just seemed reasonable to be able to do that.