Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala: pattern match problem with fully qualified classnames in parameterization

I have a little problem in pattern matching an object in Scala when it is parameterized with a fully qualified class name. This is based on Scala 2.9.0.1. Anyone knows what's wrong with this code?

scala> "foo" match {
 | case y : Seq[Integer] =>
 | case y : Seq[java.lang.Integer] =>
<console>:3: error: ']' expected but '.' found.
   case y : Seq[java.lang.Integer] =>

Why does the first version work, but the latter fail? The problem only seems to occur when a fully qualified classname is used for the parameterization.

like image 874
Frank Avatar asked Sep 14 '11 08:09

Frank


2 Answers

From the Scala Language Specification, section 8.1 Patterns, the identifier after the : needs to be what is referred to as a Type Pattern, defined in Section 8.2:

Type patterns consist of types, type variables, and wildcards. A type pattern T is of one of the following forms:

...

A parameterized type pattern T [a(1), . . . , a(n)], where the a(i) are type variable patterns or wildcards _. This type pattern matches all values which match T for some arbitrary instantiation of the type variables and wildcards. The bounds or alias type of these type variable are determined as described in (§8.3).

...

A type variable pattern is a simple identifier which starts with a lower case letter. However, the predefined primitive type aliases unit, boolean, byte, short, char, int, long, float, and double are not classified as type variable patterns.

So, syntactically, you can't use a fully qualified class as a type variable pattern IN THIS POSITION. You can however, use a type alias, so:

type JavaInt = java.lang.Integer
List(new java.lang.Integer(5)) match {
    case y: Seq[JavaInt] => 6
    case _ => 7
}

will return 6 as expected. The problem is that as Alan Burlison points out, the following also returns 6:

List("foobar") match {
    case y: Seq[JavaInt] => 6
    case _ => 7
}

because the type is being erased. You can see this by running the REPL, or scalac with the -unchecked option.

like image 165
Matthew Farwell Avatar answered Apr 05 '23 12:04

Matthew Farwell


In fact your first example doesn't work either. If you run the REPL with -unchecked, you'll see the following error:

warning: non variable type-argument Integer in type pattern Seq[Integer] is unchecked since it is eliminated by erasure

So you can't actually do what you are trying to do - at run-time there's no difference between a List[Integer] and a List[AnythingElse], so you can't pattern-match on it. You might be able to do this with a Manifest, see http://ofps.oreilly.com/titles/9780596155957/ScalasTypeSystem.html#Manifests and http://www.scala-blogs.org/2008/10/manifests-reified-types.html

like image 43
Alan Burlison Avatar answered Apr 05 '23 13:04

Alan Burlison