I really like static typing, but sometimes it can get in your way. For instance if you have a collection of objects and you want to perform an operation on the objects of a certain subclass you can run into problems. I’ve run the following code in Scala 2.8

// this is easy since everything are Strings scala> List("one", "two", "three") res0: List[java.lang.String] = List(one, two, three) scala> res0.foreach(x => println(x.length())) 3 3 5 // with a mixed collection it gets harder scala> List("one", 2, "three", 4.0) res2: List[Any] = List(one, 2, three, 4.0) scala> res2.foreach(x => println(x.length())) <console>:6: error: value length is not a member of Any // it is not enough to just filter out the objects that are Strings scala> res2.filter(_.isInstanceOf[String]) res4: List[Any] = List(one, three) // as we still have a List of Any scala> res4.foreach(x => println(x.length())) <console>:7: error: value length is not a member of Any // both filtering and mapping is needed scala> res2.filter(_.isInstanceOf[String]).map(_.asInstanceOf[String]) res6: List[String] = List(one, three) // finally it works scala> res6.foreach(x => println(x.length())) 3 5 // another option is to use pattern matching scala> res2.foreach(_ match { case x:String => println(x.length); case _ => }) 3 5

I wanted a more elegant solution with less boiler plate so after playing around with implicit conversions and reified types I managed to come up with rather nice solution:

// define a class that implements a restrictTo method scala> class IterableWithRestrictTo[A](from:Iterable[A]) { | def restrictTo[B](implicit m: scala.reflect.Manifest[B]) = { | from.filter(m.erasure.isInstance(_)).map(_.asInstanceOf[B]) | } | } defined class IterableWithRestrictTo // define implicit conversion scala> implicit def makeIterableWithRestrictTo[A](from : Iterable[A]) = { | new IterableWithRestrictTo(from) | } makeIterableWithRestrictTo: [A](from: Iterable[A])IterableWithRestrictTo[A] scala> List("one", 2, "three", 4.0) res0: List[Any] = List(one, 2, three, 4.0) // restrict to objects of type String scala> res0.restrictTo[String] res1: Iterable[String] = List(one, three) // works since the collection have correct type scala> res1.foreach(x => println(x.length())) 3 5

Using the name restrictTo clearly shows that not only is there a type conversion, but also a restriction to a subset of the elements. Notice that the manifest is needed to get the reified type, since the type B is actually erased at compile time. Read more about reified types in Scala.

Let me know you have another solution!