Wednesday, November 18, 2009

Manifests

Added in Scala 2.7 as an experimental feature is the manifest class it is a handy class allowing for very limited type reification. Take the following example:
def inspect[T](l:List[T])
If you want to know they type of T in Java you are out of luck because that type information is gone. However, Scala offers help through manifests.
  1. def inspect[T](l:List[T])(implicit manifest : scala.reflect.Manifest[T]) = println(manifest.toString)

This code snippet will print out the string representation of type T.

More Examples:
  1. scala> def inspect[T](l:List[T])(implicit manifest : scala.reflect.Manifest[T]) = println(manifest.toString)
  2. inspect: [T](List[T])(implicit scala.reflect.Manifest[T])Unit
  3. scala> inspect(List(1,2,3,4))
  4. int
  5. scala> inspect(List(List(1,2),List(3,4)))
  6. scala.List[int]
  7. scala> inspect(List(List(List(1),List(2)),List(List(3),List(4))))
  8. scala.List[scala.List[int]]
  9. scala> val l:List[Iterable[Int]] = List(List(1,2))  
  10. l: List[Iterable[Int]] = List(List(1, 2))
  11. scala> inspect(l)                                                                                           
  12. scala.collection.Iterable[Int]
  13. scala> class MV[T](val v:T)(implicit m:scala.reflect.Manifest[T]) { println(m.toString) }
  14. defined class MV
  15. scala> new MV(1)
  16. Int
  17. res1: MV[Int] = MV@180e6899
  18. scala> class MV2[T](val v:T)(implicit m:scala.reflect.Manifest[T]) {                     
  19.      | def isA[A](implicit testManifest:scala.reflect.Manifest[A]) = m.toString == testManifest.toString
  20.      | }
  21. defined class MV2
  22. scala> val x = new MV2(19)
  23. x: MV2[Int] = MV2@41ff8506
  24. scala> x.isA[String]
  25. res2: Boolean = false
  26. scala> x.isA[Int]   
  27. res3: Boolean = true
  28. scala> def isA[A](o:Object)(implicit m:Manifest[A]) = {
  29.      | val `class` = Class.forName(m.toString)         
  30.      | `class`.isAssignableFrom(o.getClass)            
  31.      | }
  32. isA: [A](o: java.lang.Object)(implicit m: scala.reflect.Manifest[A])Boolean
  33. scala> isA[java.lang.Integer](java.lang.Integer.valueOf(19))
  34. res6: Boolean = true

2 comments:

  1. `class`.isAssignableFrom(o.getClass)
    should be written as
    `class`.isInstance(o)

    ReplyDelete
  2. Amazing. The 'isA' comparison example really helped me wrap my head around this.

    ReplyDelete