Why does this print wtf? Does pattern matching not work on structural types?
"hello" match {
case s: { def doesNotExist(i: Int, x: List[_]): Double } => println("wtf?")
case _ => println("okie dokie")
}
Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.
Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.
Lost your password? Please enter your email address. You will receive a link and will create a new password via email.
Please briefly explain why you feel this question should be reported.
Please briefly explain why you feel this answer should be reported.
Please briefly explain why you feel this user should be reported.
Running this example in the Scala interpreter with unchecked warnings on (
scala -unchecked) produces the following warning:warning: refinement AnyRef{def doesNotExist(Int,List[_]): Double} in type pattern is unchecked since it is eliminated by erasure. Unfortunately, a generic type like this cannot be checked at runtime as the JVM doesn’t have reified generics.All that the JVM sees in this pattern match is:
EDIT: In response to your comments, I have been thinking about a solution but didn’t have the time to post it yesterday. Unfortunately, even if it should work, the compiler fails to inject the proper
Manifest.The problem you want to solve is to compare if an object is of a given structural type. Here’s some code I’ve been thinking of (Scala 2.8-r20019, as Scala 2.7.6.final crashed on me a couple of times while playing with similar ideas)
Method
isFoobasically compares the manifests of the classxofFoo. In an ideal world, the manifest of a structural type should be equal to the manifest of any type containing the required methods. At least that’s my train of thought. Unfortunately this fails to compile, as the compiler injects aManifest[AnyRef]instead of aManifest[Foo]when callinggetManifest[Foo]. Interestingly enough, if you don’t use a structural type (for example,type Foo = String), this code compiles and works as expected. I’ll post a question at some point to see why this fails with structural types — is it a design decision, or it is just a problem of the experimental reflection API.Failing that, you could always use Java reflection to see if an object contains a method.
which works as expected:
… but it’s not very nice.
Also, note that the structure of a structural type is not available at runtime. If you have a method
def foo(x: {def foo: Int}) = x.foo, after erasure you getdef foo(x: Object) = [some reflection invoking foo on x], the type information being lost. That’s why reflection is used in the first place, as you have to invoke a method on anObjectand the JVM doesn’t know if theObjecthas that method.