In
trait Expr
case class Number(n: Int) extends Expr
case class Sum(e1: Expr, e2: Expr) extends Expr
object CaseExample {
def eval(e: Expr): Int = e match {
case Number(n) => n
case Sum(e1, e2) => eval(e1) + eval(e2)
}
def main(args: Array[String]) {
println(eval(Sum(Number(1), Number(2)))) //> 3
}
}
there is quite a bit of syntactic sugar going on. I get that case is implicitly creating two objects
object Number extends Expr {
def apply(n: Int) = new Number(n)
}
object Sum extends Expr {
def apply(e1: Expr, e2: Expr) = new Sum(e1, e2)
}
and that is why we can write e.g. Sum(...) and still instantiate an object via a class, since Sum(...) is also syntactic sugar for Sum.apply(...).
Am I right that match construct is also syntactic sugar?
If it is, how is - e.g. case Number(n) - rewritten by the compiler?
I am asking, because I don't see that n in case Number(n) is anywhere defined and/or bound to a value. Strangely enough, in a match construct the case of the first letter matters (if it where upper case it would be a constant). This is strange because as far as I know this is only in a match construct of relevance, so I have no idea how this would be de-sugared.
Yes,
matchis syntactic sugar. It calls theunapplymethod on your object. Daniel Westheide has a nice blog post about it.Specifically, when you define your
case classforNumber, here's what the compiler actually generates:As you can see, the
Numbercompanion object comes with a compiler-generatedunapplymethod.You can find a thorough description of the design of Scala's pattern matching facility here.
-- EDIT --
If you want to see the actual, compiler generated code, run
scalac -print Number.scala. Here are the relevant bits:If you write a
matchexpression, you can similarly runscalac -printto see how thematchitself is desugared (basically:ifandelseexpressions).