Reputation: 41939
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?
Upvotes: 3
Views: 577
Reputation: 149598
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.
Upvotes: 1