I am trying to understand the scala unapply method.
Below is my understanding. Say if I have a Person object:
class Person(val fname: String, val lname: String)
object Person{
def unapply(x: Person) : Option[(String, String)] =
Some(x.fname,x.lname)
}
new Person("Magic", "Mike") match {
case Person(x, y) => s"Last Name is ${y}"
case _ => "Unknown"
}
This i presume the case calls something like:
val temp = Person.unapply(new Person("Magic", "Mike"))
if (temp != None) { val (x, y) = temp.get }
else { <go to next case> }
but how does below unapply work when i have like below:
new Person("Magic", "Mike") match {
case Person("Harold", y) => s"Last Name is ${y}"
case Person("Magic", y) => s"Last Name is ${y}"
case _ => "Unknown"
}
How does it access the value of fname("Magic") in unapply method and give me the same/correct result as the first one?
Running scalac
with -Xprint:patmat
will show you how syntactic trees look after pattern matching phase:
scalac -Xprint:patmat test.scala
case <synthetic> val x1: Person = new Person("Magic", "Mike");
case10(){
<synthetic> val o12: Option[(String, String)] = Person.unapply(x1);
if (o12.isEmpty.unary_!)
{
<synthetic> val p3: String = o12.get._1;
val y: String = o12.get._2;
if ("Harold".==(p3))
matchEnd9(scala.StringContext.apply("Last Name is ", "").s(y))
else
case11()
}
else
case11()
};
case11(){
<synthetic> val o14: Option[(String, String)] = Person.unapply(x1);
if (o14.isEmpty.unary_!)
{
<synthetic> val p5: String = o14.get._1;
val y: String = o14.get._2;
if ("Magic".==(p5))
matchEnd9(scala.StringContext.apply("Last Name is ", "").s(y))
else
case13()
}
else
case13()
};
case13(){
matchEnd9("Unknown")
};
As you can see, for each case first it calls unapply
on the matched object, then if Option
is not empty (so it has matched), it checks if one of the elements of tuple is equal to expected value, if so then it matches to the closure for this case.