In the following code, I'm trying to understand the usage of Foo#unapply : Option[Int] with respect to pattern matching.
$ls
Test.scala
$cat Test.scala
object Test {
case class Foo(x: Int)
def f(foo: Foo): Unit = foo match {
case Foo(_) => ()
}
}
It compiles:
$scalac Test.scala
$ls
Test$.class Test$Foo$.class Test$Foo.class Test.class Test.scala
I ran javap -c -v X.class | grep unapply on each *class file. But, I did not find any results.
Please explain how Foo#unapply gets used in pattern matching. Also, where can I find the corresponding JVM bytecode instructions?
If you compile with -Xprint:typer or -print, you'll see the generated code. This is the cleaned up version of apply and unapply, compiled with scalac -Xprint:typer Test.scala:
case def apply(x: Int): com.yuval.Test.Foo = new Foo(x);
case def unapply(x$0: com.yuval.Test.Foo): Option[Int] = if (x$0.==(null))
scala.this.None
else
Some.apply[Int](x$0.x);
And f remains the same:
def f(foo: com.yuval.Test.Foo): Unit = foo match {
case (x: Int)com.yuval.Test.Foo(_) => ()
}
And this is the Java decompiled code from Test$.class:
public void f(Test.Foo foo) {
Test.Foo localFoo = foo;
if (localFoo != null) {
BoxedUnit localBoxedUnit = BoxedUnit.UNIT;
} else {
throw new MatchError(localFoo);
}
}
And this is the bytecode produced with java -c -p Test$.class:
public void f(com.yuval.Test$Foo);
Code:
0: aload_1
1: astore_2
2: aload_2
3: ifnull 11
6: getstatic #20 // Field scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
9: astore_3
10: return
11: new #22 // class scala/MatchError
14: dup
15: aload_2
16: invokespecial #25 // Method scala/MatchError."<init>":(Ljava/lang/Object;)V
19: athrow
The pattern match here turns into a simple type check.
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