One interesting thing that has probably gone unnoticed by most, however, is that it can do more than what the old pattern matcher did, in at least one respect: it can match against abstract types, provides a ClassTag.
To understand that better, consider this REPL session on Scala 2.9.2:
scala> def f[T: ClassManifest](l: List[Any]) = l collect { | case x: T => x | } <console>:8: warning: abstract type T in type pattern T is unchecked sin ce it is eliminated by erasure case x: T => x ^ f: [T](l: List[Any])(implicit evidence$1: ClassManifest[T])List[T] scala> f[String](List(1, 2.0, "three")) res0: List[String] = List(1, 2.0, three)
Now let's look at what can be done with Scala 2.10.0:
scala> import scala.reflect.ClassTag import scala.reflect.ClassTag scala> def f[T: ClassTag](l: List[Any]) = l collect { | case x: T => x | } f: [T](l: List[Any])(implicit evidence$1: scala.reflect.ClassTag[T])List [T] scala> f[Int](List(1, 2.0, "three")) // It can't find Int because they are boxed res0: List[Int] = List() scala> f[String](List(1, 2.0, "three")) // But AnyRefs are ok res1: List[String] = List(three)
Note that it doesn't reify types -- that is, it can't tell whether your List[Any] is a List[String], but it does go a bit further than what was possible before.
This seems like it just adds a little syntactic sugar to what one could already do with manifests and a guard. It seems potentially useful, but only really for interfacing with badly written libraries that throw away type information in the first place.
ReplyDeleteCool.
ReplyDeleteI find it slightly amusing that your example shows that boxed values still don't work, but now with no warning. In that case, I think I would prefer the previous behavior.
ReplyDelete