I'm looking to understand the compile-time errors generated by the following Scala code:
class MyClass {
def determineType(x:Any):String = {
x match {
case Int => "It's an int."
case Float => "It's a Float."
case CIn => "It's a CIn without a specifier."
case c:CIn => "It's a CIn with a specifier."
case DIn=> "It's a DIn without a specifier." // Error:Cannot resolve symbol DIn
case d:DIn=> "It's a DIn with a specifier."
case _ => "It's something else."
}
}
case class CIn()
class DIn
} // End class definition
def determineType(x:Any):String = {
x match {
case Int => "It's an int"
case Float => "It's a Float"
case COut => "It's a COut without a specifier." // Error: Wrong forward reference
case c:COut => "It's a COut with a specifier."
case DOut=> "It's a DOut without a specifier." // Error: Cannot resolve symbol DOut.
case d:DOut=> "It's a DOut with a specifier."
case _ => "It's something else."
}
}
case class COut()
class DOut()
In the version of determineType
within MyClass
, both the case class
CIn
as well as the regular class DIn
are defined and declared after determineType
. A symbol resolution error is generated when trying to match against a DIn
without a specifier variable.
At script scope, we similarly define a case class
Cout
and a regular class
DOut
. In the script-scope version of determineType
we have two different errors. The first one is generated when referring to a case class
type (Cout
) without a specifier, and it reads "Wrong forward reference". The second one is generated when referring to a regular class
type (DOut
) without a specifier, and it is a symbol resolution error.
I'm new to the language and am thus not sure why the inclusion of specifiers in the case
statements affects the way that forward references are treated.
If your write a match clause case Foo =>
you are not matching for a type (or class) Foo
but a value Foo
. So case Int =>
does not match for an integer value, and case DIn =>
does not work because there is no value (or object) DIn
.
The following works:
val Foo = 1
object Bar
def testVal(x: Any) = x match {
case Foo => "it's Foo"
case Bar => "it's Bar"
case _ => "none of the above"
}
testVal(1) // Foo!
testVal(Bar) // Bar
testVal(Foo + 1) // none
If you want to match for the instance of a class instead, you need to match for a clause case b: Baz =>
or case _: Baz
(if you are not interested in binding the instance to a value). For case classes, you can further more use the automatically provided extractor, so with case class Baz()
you can also match as case Baz() =>
. This usually makes more sense when Baz
contains arguments which are hereby extracted:
case class Baz(i: Int)
def testType(x: Any) = x match {
case Baz(3) => "Baz with argument 3"
case b: Baz => "Baz with argument other than 3"
case Baz => "Baz companion!"
case _ => "none of the above"
}
testType(Baz) // companion object!
testType(Baz(3))
testType(Baz(4))
A case class also gives you a companion object
so here you could actually match for that object using case Baz =>
. An object
is a kind of value.
Finally, I don't know which Scala version you are using, but in regular current Scala, you cannot omit the match
keyword on the RHS of your definition of determineType
:
def determineType(x: Any): String = {
case _ => "anything"
}
<console>:53: error: missing parameter type for expanded function The argument types of an anonymous function must be fully known. (SLS 8.5) Expected type was: String def determineType(x: Any): String = { ^
You have to write:
def determineType(x: Any): String = x match /* ! */ {
case _ => "anything"
}