score:6
This is done outside of the REPL, but you can compile your code using scalac with the -print option. Doing scalac -help
will give you this description of the option:
-print Print program with Scala-specific features removed.
I tried it with this small program:
object Test {
def main(args: Array[String]): Unit = {
val a = (x: Int) => x * x
}
}
And it gave me this output:
$ scalac -print Test.scala
[[syntax trees at end of cleanup]] // Test.scala
package <empty> {
object Test extends Object {
def main(args: Array[String]): Unit = {
val a: Function1 = {
(new <$anon: Function1>(): Function1)
};
()
};
def <init>(): Test.type = {
Test.super.<init>();
()
}
};
@SerialVersionUID(value = 0) final <synthetic> class anonfun$1 extends scala.runtime.AbstractFunction1$mcII$sp with Serializable {
final def apply(x: Int): Int = anonfun$1.this.apply$mcII$sp(x);
<specialized> def apply$mcII$sp(x: Int): Int = x.*(x);
final <bridge> <artifact> def apply(v1: Object): Object = scala.Int.box(anonfun$1.this.apply(scala.Int.unbox(v1)));
def <init>(): <$anon: Function1> = {
anonfun$1.super.<init>();
()
}
}
}
score:3
There's nothing at runtime which will print compiled code nicely.
You could write a macro which will print the source code of the tree and use that? Most macro tutorials start with a macro for printing source code -- see e.g. http://www.warski.org/blog/2012/12/starting-with-scala-macros-a-short-tutorial/
Perhaps:
// Given a partial function "pf", return the source code for pf
// as a string as well as the compiled, runnable function itself
def functionAndSource(pf: PartialFunction[Any, Any]): (String, PartialFunction[Any, Any]) = macro functionAndSourceImpl
def functionAndSourceImpl = ...
val pm1: (String, PartialFunction[Any, Any]) = functionAndSource {
case "foo" => R1
}
This isn't ever going to be that easy or nice in Scala. Scala isn't Lisp or Ruby: it's a compiled language and it is not optimised for reflection on the code itself.
(See Scala Pattern Matching pretty printed for a very similar question.)
score:3
Try my small scala-to-java tool. It complies given scala source and then decompiles it into java using Procyon decompiler.
For you scala input:
val a = (x: Int) => x * x
It shows this decompiled output:
import scala.*;
import scala.runtime.*;
public final class _$$anon$1$$anonfun$1 extends AbstractFunction1$mcII$sp implements Serializable {
@Override
public final int apply(final int x) {
return this.apply$mcII$sp(x);
}
@Override
public int apply$mcII$sp(final int x) {
return x * x;
}
}
import scala.*;
public final class _$$anon$1 {
private final Function1<Object, Object> a = new _$$anon$1$$anonfun._$$anon$1$$anonfun$1(this);
private Function1<Object, Object> a() {
return (Function1<Object, Object>)this.a;
}
}
score:5
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.
score:11
It's not as handy as same functionality in, say, clojure, since it shows compiled code but you can either get advantage of :javap
:
scala> :javap -help
usage :javap [opts] [path or class or -]...
-help Prints this help message
-raw Don't unmangle REPL names
-app Show the DelayedInit body of Apps
-fun Show anonfuns for class or Class#method
-verbose/-v Stack size, number of locals, method args
-private/-p Private classes and members
-package Package-private classes and members
-protected Protected classes and members
-public Public classes and members
-l Line and local variable tables
-c Disassembled code
-s Internal type signatures
-sysinfo System info of class
-constants Static final constants
scala> :javap -s a
Compiled from "<console>"
public class {
public static final MODULE$;
descriptor: L;
public static {};
descriptor: ()V
public scala.Function1<java.lang.Object, java.lang.Object> a();
descriptor: ()Lscala/Function1;
public ();
descriptor: ()V
}
Or instruct REPL to output code internals on compilation with scala -Xprint:typer
(though it might be overly verbose, maybe someone can suggest less wordy compiler stage to use).
BTW, as you can see in :javap output, every REPL expression is implicitly wrapped with surrounding code, don't be confused -- scala does not perform it normally.
Source: stackoverflow.com
Related Query
- Viewing the contents in <function1> from the scala repl
- Why can I use a Java lib from the Scala REPL but not from a script?
- Running the scala REPL from gradle?
- Scala REPL from cmd: The syntax of the command is incorrect
- How do I get the Scala version from within Scala itself?
- Remove Characters from the end of a String Scala
- How does the “scala.sys.process” from Scala 2.9 work?
- How are Scala collections able to return the correct collection type from a map operation?
- How do I access scala documentation from the repl?
- Scala 2.10 reflection, how do I extract the field values from a case class, i.e. field list from case class
- How do I abstract the domain layer from the persistence layer in Scala
- How to populate java.util.HashMap on the fly from Scala code?
- all but the last item from a Scala Iterator (a.k.a. Iterator.init)
- Instantiate a Scala class from Java, and use the default parameters of the constructor
- Executing shell commands from Scala REPL
- How to run an external file from within the scala interactive interpreter (REPL)?
- What is the proper way to remove elements from a scala mutable map using a predicate
- Is there a way to make the Scala REPL not stop with CTRL-C
- Why can’t Scala infer the path of a path-dependent type—even from an explicit self-reference?
- Is there a tool for Scala to clean all the unused imports from all the code files?
- Dropping multiple columns from Spark dataframe by Iterating through the columns from a Scala List of Column names
- How can I idiomatically "remove" a single element from a list in Scala and close the gap?
- How to call main method of a Scala program from the main method of a java program?
- Read the data from HDFS using Scala
- Exiting Spark-shell from the scala script
- How to upgrade Scala to a newer version from the command line?
- Calling into Play framework app from the Scala console
- What is the difference between Clojure REPL and Scala REPL?
- Reading Multiple Inputs from the Same Line the Scala Way
- How can an implicit be unimported from the Scala repl?
More Query from same tag
- Recursive method call in Apache Spark
- I don't know how to do the same using parquet file
- Scala case class instantiate when you have not-used-in-equals properties
- Scala - Currying and default arguments
- Scala Recursion and Units
- Testing Samza with RocksDB application with SBT
- Is there a data structure / library to do in memory olap / pivot tables in Java / Scala?
- How to avoid boxing when composing numbers in base 3 in Scala
- SLF4J Multiple bindings
- Yield an ArrayBuffer (or other mutable Collection type) from a for loop in Scala
- Scala: Implementing map and withFilter in a simple custom type
- Comparing intersection between two nodes using broadcast variable and using RDD.filter in Spark GraphX
- Emulating variadic templates in Scala
- Type mismatch with map and flatMap
- Scala in Java code using Spring without Default Constructor
- How do I properly namespace a play application?
- Spark Scala Convert Sparse to Dense Feature
- How can I insert values of a DataFrame column into a list
- Why this class have to be case class?
- Akka Balancing Pool with variable-size Thread-Pool-Executor
- Does Akka regulate actors based on available resources?
- Scala - XML parsing tag not working properly
- How varargs like Int*, String* implemented in Scala?
- Add a cookie in a Play Framework 2.x filter?
- In which controller will action builder executes
- Scala get content from REST API with header
- I have a StructType schema. I want to store it in a separate file in the same format and read it in my Spark program from that file
- Supertype for scalaquery query
- Scala promise does not work if I encapsulate it in a commodity function
- Why Scala fail to recognize Null type as a subtype of T in generic function type parameter inference?