Thursday, February 11, 2010

Selection with Implicit Methods

This tip is a cool tip based on Daniel's Use Implicits to Select Types post. That post goes into more detail.

The idea is that depending on a given parameter of type T a particular type of object is required. There are several ways to do this. One would be to use matching to match the type T and create the correct object. Most likely the biggest draw back to matching is caused by type erasure. The following solution gets around that issue.

Two very interesting points.
  1. Implicit methods do not require parameters. They can be selected based only on type parameters
  2. Implicit methods are not subject to type erasure
  1. // the base class we need
  2. scala> abstract class X[T] { def id :Unit }
  3. defined class X
  4. /*
  5. One of the types we need created.  It is the catch all case
  6. */
  7. scala> implicit def a[T] =new X[T] { def id =println("generic") }
  8. a: [T]X[T]
  9. /*
  10. A specific subclass for integers
  11. */
  12. scala> implicit def b =new X[Int] { def id =println("Int") }
  13. b: X[Int]
  14. /*
  15. One simple usage.  The most specific implicit will be used to 
  16. create the object to be passed to g.  
  17. */
  18. scala> def f[T](a :T)(implicit g :X[T]) = g.id
  19. f: [T](a: T)(implicit g: X[T])Unit
  20. scala> f(5)
  21. Int
  22. scala> f('c')
  23. generic
  24. /*
  25. This example demonstrates how erasure is not an issue because 
  26. the selection of the implicit is done at compile time so 
  27. the correct type is selected.  If a match was used instead 
  28. then a more complicated solution would be required
  29. */
  30. scala> def g[T](l:List[T])(implicit i:X[T]) = i.id          
  31. g: [T](l: List[T])(implicit i: X[T])Unit
  32. scala> g(List(1,2,3))
  33. Int
  34. scala> g(List("a",2,3))
  35. generic

1 comment: