To see function literals, use :javap -fun
:
$ scala
Welcome to Scala version 2.11.7 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_51).
Type in expressions to have them evaluated.
Type :help for more information.
scala> def f = (1 to 10) map (_ * 2)
f: scala.collection.immutable.IndexedSeq[Int]
scala> :javap -fun f
Compiled from "<console>"
public final class $anonfun$f$1 extends scala.runtime.AbstractFunction1$mcII$sp implements scala.Serializable {
public static final long serialVersionUID;
public final int apply(int);
public int apply$mcII$sp(int);
public final java.lang.Object apply(java.lang.Object);
public $anonfun$f$1();
}
That's the anonymous function passed to map.
To filter for the apply methods, which are the body of the function, use a trailing #
or f#apply
:
scala> :javap -fun f#
public final int apply(int);
public int apply$mcII$sp(int);
public final java.lang.Object apply(java.lang.Object);
That includes specialized methods.
scala> :javap -fun -prv f#
public final int apply(int);
flags: ACC_PUBLIC, ACC_FINAL
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: iload_1
2: invokevirtual #21 // Method apply$mcII$sp:(I)I
5: ireturn
LocalVariableTable:
Start Length Slot Name Signature
0 6 0 this L$line3/$read$$iw$$iw$$anonfun$f$1;
0 6 1 x$1 I
LineNumberTable:
line 10: 0
public int apply$mcII$sp(int);
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: iload_1
1: iconst_2
2: imul
3: ireturn
LocalVariableTable:
Start Length Slot Name Signature
0 4 0 this L$line3/$read$$iw$$iw$$anonfun$f$1;
0 4 1 x$1 I
LineNumberTable:
line 10: 0
public final java.lang.Object apply(java.lang.Object);
flags: ACC_PUBLIC, ACC_FINAL, ACC_BRIDGE, ACC_SYNTHETIC
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: aload_1
2: invokestatic #32 // Method scala/runtime/BoxesRunTime.unboxToInt:(Ljava/lang/Object;)I
5: invokevirtual #34 // Method apply:(I)I
8: invokestatic #38 // Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
11: areturn
LocalVariableTable:
Start Length Slot Name Signature
0 12 0 this L$line3/$read$$iw$$iw$$anonfun$f$1;
0 12 1 v1 Ljava/lang/Object;
LineNumberTable:
line 10: 0
scala>
For vals, first look at the constructor for the evaluation:
scala> :javap -fun c
Failed: No closures found.
scala> :javap -prv c
[snip]
public $line7.$read$$iw$$iw$();
flags: ACC_PUBLIC
Code:
stack=4, locals=1, args_size=1
0: aload_0
1: invokespecial #20 // Method java/lang/Object."<init>":()V
4: aload_0
5: putstatic #22 // Field MODULE$:L$line7/$read$$iw$$iw$;
8: aload_0
9: getstatic #27 // Field $line6/$read$$iw$$iw$.MODULE$:L$line6/$read$$iw$$iw$;
12: invokevirtual #30 // Method $line6/$read$$iw$$iw$.b:()Lscala/Function1;
15: new #32 // class $line7/$read$$iw$$iw$$anonfun$1
18: dup
19: invokespecial #33 // Method $line7/$read$$iw$$iw$$anonfun$1."<init>":()V
22: invokeinterface #39, 2 // InterfaceMethod scala/Function1.apply:(Ljava/lang/Object;)Ljava/lang/Object;
[snip]
and then cut/paste the name of the anonfun, optionally adding the #
to filter for just the apply methods:
scala> :javap -prv $line7/$read$$iw$$iw$$anonfun$1#
public final boolean apply(int);
flags: ACC_PUBLIC, ACC_FINAL
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: iload_1
2: invokevirtual #18 // Method apply$mcZI$sp:(I)Z
5: ireturn
LocalVariableTable:
Start Length Slot Name Signature
0 6 0 this L$line7/$read$$iw$$iw$$anonfun$1;
0 6 1 x I
LineNumberTable:
line 12: 0
public boolean apply$mcZI$sp(int);
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: iload_1
1: iconst_2
2: irem
3: iconst_0
4: if_icmpne 11
7: iconst_1
8: goto 12
11: iconst_0
12: ireturn
[snip]
The function stored in c
:
scala> $intp.isettings.unwrapStrings = false
$intp.isettings.unwrapStrings: Boolean = false
scala> c.getClass
res4: Class[_ <: Int => Boolean] = class $line3.$read$$iw$$iw$$anonfun$1$$anonfun$apply$1
scala> :javap -prv $line3.$read$$iw$$iw$$anonfun$1$$anonfun$apply$1
[snip]
The -raw
option for :javap
exposes the REPL's packages and wrapping objects. To see them in ordinary output, you have to turn off output filtering as shown.
Or:
scala> $intp.withoutUnwrapping(println(c.getClass))
class $line3.$read$$iw$$iw$$anonfun$1$$anonfun$apply$1
Usually anon funs are brief, so filtering for the apply method is not necessary.
Note that I stripped out this feature for the transition to Java 8 lambdas, since the encoding has been in flux. Maybe it will be restored at some point.