I have simple type hierarchy in Scala:
trait A {
trait A1
}
object B extends A {
case object B1 extends A1
}
object C extends A {
case object C1 extends A1
}
And, I'm gonna use these types like that:
def get(): Any = C.C1
get() match {
case _: B.A1 => println("B")
case _: C.A1 => println("C")
case _: A#A1 => println("Any")
}
Surprisingly, I'm getting B
printed (I've expected C
).
Why compiler treats C.C1
as instance of B.A1
?
Following are the different types of Scala Pattern Matching, let’s discuss them one by one: a. Variable Patterns An identifier for a variable pattern begins with a lowercase letter. It matches a value and binds to it the variable name. The wildcard pattern ‘_’ is a special case of this. b. Typed Patterns
TypeTag The Scala reflection API has a mechanism called TypeTag that allows you to inspect the type of instances, including the types of generics, at runtime. As the docs, state “TypeTags can be thought of as objects which carry along all type information available at compile time, to runtime”.
Not only we can use it to replace if-else ladders also we can use it to deconstruct a value into its constituent parts. Scala pattern matching is made of constants, variables, constructors, and type tests. Using such a pattern, we can test if a value follows a pattern. We can only bind a variable name once in a pattern.
In the meantime, see the scala.util.Try documentation for more information. (One thing you should get from this example is that Try/Success/Failure is an alternative to using Option/Some/None.
This is a known bug.
Scalac does generate a warning for this using the -unchecked
flag:
warning: The outer reference in this type test cannot be checked at run time.
case _: B.A1 => println("B")
^
So right now, B.A1
and C.A1
appear the same to the compiler in the pattern match, because it doesn't check the outer reference to B
or C
.
See this related discussion.
And SI-4440
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With