According to this, Scala methods belong to a class. However, if I define a method in REPL or in a script that I then execute using scala, what class does the method belong to ?
scala> def hoho(str:String) = {println("hoho " + str)}
hoho: (str: String)Unit
scala> hoho("rahul")
hoho rahul
In this example, what class does the method belong to ?
The REPL wraps all your statements (actually rewrites your statements) in objects automagically. You can see it in action if you print the intermediate code by using the -Xprint:typer option:
scala> def hoho(str:String) = {println("hoho " + str)}
[[syntax trees at end of typer]]// Scala source: <console>
package $line1 {
final object $read extends java.lang.Object with ScalaObject {
def this(): object $line1.$read = {
$read.super.this();
()
};
final object $iw extends java.lang.Object with ScalaObject {
def this(): object $line1.$read.$iw = {
$iw.super.this();
()
};
final object $iw extends java.lang.Object with ScalaObject {
def this(): object $line1.$read.$iw.$iw = {
$iw.super.this();
()
};
def hoho(str: String): Unit = scala.this.Predef.println("hoho ".+(str))
}
}
}
}
So your method hoho is really $line1.$read.$iw.$iw.hoho. Then when you use hoho("foo") later on, it'll rewrite to add the package and outer objects.
Additional notes: for scripts, -Xprint:typer (-Xprint:parser) reveals that the code is wrapped inside a code block in the main(args:Array[String]) of an object Main. You have access to the arguments as args or argv.
Related
In Scala we can define functions/methods inside other functions/methods in same class, and those functions are locally scoped to the functions/methods they are defined to, unable to access outside of from the function they are defined inside. Would that make those locally defined functions private access specifier in Scala?
Those functions are basically local variables, and as such don't have access modifiers. There's no real need to give them modifiers since the method inside which they are defined is the only place where they can be accessed, and they're only used in a very small part of your application. I suppose they are private by default, if you take private to mean that they can only be accessed in the lowest scope they are in.
As #Luis Miguel Mejía Suárez and #Mario Galic pointed out, these local/nested functions get turned into private (final) methods in the same class. So in a way, yes, they are private (to the class they are in, not the enclosing method), but you cannot actually access them from other methods in the same class without using reflection or something else.
Executing scalac -Xshow-phases outputs compiler phases and the following seems interesting
lambdalift 17 move nested functions to top level
For example, running scalac -Xprint:lambdalift on
class O {
def f() = {
def nested() = 42
nested()
}
}
outputs on my machine with Scala 2.13.2 something like
class O {
def f(): Int = nested();
private def nested(): Int = 42;
}
where we see nested method became private member method of the enclosing class. You could try exploring what happens for inner functions using the same technique.
On language level according to Scala specification there are only the following access modifiers
https://scala-lang.org/files/archive/spec/2.11/05-classes-and-objects.html#modifiers
<no modifier>
private
private[C]
private[this]
protected
protected[C]
protected[this]
So on language level the answer for your question is that there is no access modifier specific for nested methods.
On implementation level there are plenty of modifiers and flags (some of them are access modifiers)
https://github.com/scala/scala/blob/2.13.x/src/reflect/scala/reflect/internal/Flags.scala
PROTECTED
PRIVATE
LOCAL
SEALED
METHOD
...
We can peep on compiler if we create an annotation
import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.language.experimental.macros
import scala.reflect.macros.blackbox
#compileTimeOnly("enable macro paradise")
class printMethodModifiers extends StaticAnnotation {
def macroTransform(annottees: Any*): Any = macro PrintMethodModifiersMacro.impl
}
object PrintMethodModifiersMacro {
def impl(c: blackbox.Context)(annottees: c.Tree*): c.Tree = {
import c.universe._
val traverser = new Traverser {
override def traverse(tree: Tree): Unit = {
tree match {
case q"${mods: Modifiers} def $_[..$_](...$_): $_ = $_" =>
println(s"tree=$tree, mods.flags=${mods.flags}")
case _ => ()
}
super.traverse(tree)
}
}
traverser.traverse(annottees.head)
q"..$annottees"
}
}
and use it to traverse the tree of class
#printMethodModifiers
class O {
def f() = {
def nested() = 42
nested()
}
}
//Warning:scalac: tree=def <init>() = {
// super.<init>();
// ()
//}, mods.flags=0
//Warning:scalac: tree=def f() = {
// def nested() = 42;
// nested()
//}, mods.flags=0
//Warning:scalac: tree=def nested() = 42, mods.flags=0
So when macro annotations are expanded in typer phase there is no difference in flags for methods and nested methods.
I am trying to understand how scoping works in the REPL. I tried following Section 5.1.1 of Joshua Suereth's book Scala in depth.This is on Windows XP, Java 7 and Scala 2.9.1. I declare a class Dinner in the REPL. The binding Dinner exists in the local scope. Then I instantiate because it is locally bound.
scala> class Dinner {
| val veggie="broccoli"
| def announceDinner(veggie: String){
| println("Dinner happens to be tasteless " + veggie + " soup")
| }
| }
defined class Dinner
scala> new Dinner
res1: Dinner = Dinner#27fb77
So far so good. The name Dinner was bound locally and we could also construct a val x that could hold a reference to new Dinner.
From what I know so far, The REPL will wrap the above code in objects internally. Okay, my knowledge of Scala is not quite as deep yet and I am trying to understand how Class might be internally wrapped by the REPL.
Is there an REPL command that can help me evaluate these objects?
Here goes a very quick and dirty way to what is going on in the REPL.
Invoke the REPL with scala -Xprint:typer
scala> class Dinner {
| val veggie="broccoli"
| def announceDinner(veggie: String){
| println("Dinner happens to be tasteless " + veggie + " soup")
| }
| }
[[syntax trees at end of typer]]// Scala source: <console>
package $line1 {
final object $read extends java.lang.Object with ScalaObject {
def this(): object $line1.$read = {
$read.super.this();
()
};
final object $iw extends java.lang.Object with ScalaObject {
def this(): object $line1.$read.$iw = {
$iw.super.this();
()
};
final object $iw extends java.lang.Object with ScalaObject {
def this(): object $line1.$read.$iw.$iw = {
$iw.super.this();
()
};
class Dinner extends java.lang.Object with ScalaObject {
def this(): $line1.$read.$iw.$iw.Dinner = {
Dinner.super.this();
()
};
private[this] val veggie: java.lang.String = "broccoli";
<stable> <accessor> def veggie: java.lang.String = Dinner.this.veggie;
def announceDinner(veggie: String): Unit = scala.this.Predef.println("Dinner happens to be tasteless ".+(veggie).+(" soup"))
}
}
}
}
}
[[syntax trees at end of typer]]// Scala source: <console>
package $line1 {
final object $eval extends java.lang.Object with ScalaObject {
def this(): object $line1.$eval = {
$eval.super.this();
()
};
private[this] val $print: String = {
$read.$iw.$iw;
"defined class Dinner\012"
};
<stable> <accessor> def $print: String = $eval.this.$print
}
}
defined class Dinner
As you can check above Dinner ends up wrapped into $line1.$read.$iw.$iw. Now let's see what happens next:
[[syntax trees at end of typer]]// Scala source: <console>
package $line2 {
final object $read extends java.lang.Object with ScalaObject {
def this(): object $line2.$read = {
$read.super.this();
()
};
final object $iw extends java.lang.Object with ScalaObject {
def this(): object $line2.$read.$iw = {
$iw.super.this();
()
};
import $line1.$read.$iw.$iw.Dinner;
final object $iw extends java.lang.Object with ScalaObject {
def this(): object $line2.$read.$iw.$iw = {
$iw.super.this();
()
};
private[this] val res0: $line1.$read.$iw.$iw.Dinner = new $line1.$read.$iw.$iw.Dinner();
<stable> <accessor> def res0: $line1.$read.$iw.$iw.Dinner = $iw.this.res0
}
}
}
}
[[syntax trees at end of typer]]// Scala source: <console>
package $line2 {
final object $eval extends java.lang.Object with ScalaObject {
def this(): object $line2.$eval = {
$eval.super.this();
()
};
lazy private[this] var $result: $line1.$read.$iw.$iw.Dinner = {
$eval.this.$print;
$line2.$read.$iw.$iw.res0
};
private[this] val $print: String = {
$read.$iw.$iw;
"res0: $line1.$read.$iw.$iw.Dinner = ".+(scala.runtime.ScalaRunTime.replStringOf($line2.$read.$iw.$iw.res0, 1000))
};
<stable> <accessor> def $print: String = $eval.this.$print
}
}
Basically the same thing as before but using $line2 instead of $line1. Notice the import $line1.$read.$iw.$iw.Dinner right before $line2.$read.$iw.$iw.
This way we can see why defining companion objects in two different lines doesn't work, they end up wrapped into different objects and companions need to be defined in the same scope/source file.
Assume, we have something like:
val x = "foo".charAt(0)
and let us further assume, we do not know the return type of the method charAt(0) (which is, of course, described in the Scala API). Is there a way, we can find out, which type the variable x has after its definition and when it is not declared explicitly?
UPDATE 1:
My initial question was not precise enough: I would like to know (for debugging reasons) what type the variable has. Maybe there is some compiler option to see what type the variable get declared to by Scala's type inference ?
Suppose you have the following in a source file named Something.scala:
object Something {
val x = "foo".charAt(0)
}
You can use the -Xprint:typer compiler flag to see the program after the compiler's typer phase:
$ scalac -Xprint:typer Something.scala
[[syntax trees at end of typer]]// Scala source: Something.scala
package <empty> {
final object Something extends java.lang.Object with ScalaObject {
def this(): object Something = {
Something.super.this();
()
};
private[this] val x: Char = "foo".charAt(0);
<stable> <accessor> def x: Char = Something.this.x
}
}
You could also use :type in the REPL:
scala> :type "foo".charAt(0)
Char
scala> :type "foo".charAt _
Int => Char
Your IDE may also provide a nicer way to get this information, as Luigi Plinge points out in a comment above.
Here's an easier version of Travis first alternative:
dcs#dcs-132-CK-NF79:~/tmp$ scala -Xprint:typer -e '"foo".charAt(0)'
[[syntax trees at end of typer]] // scalacmd8174377981814677527.scala
package <empty> {
object Main extends scala.AnyRef {
def <init>(): Main.type = {
Main.super.<init>();
()
};
def main(argv: Array[String]): Unit = {
val args: Array[String] = argv;
{
final class $anon extends scala.AnyRef {
def <init>(): anonymous class $anon = {
$anon.super.<init>();
()
};
"foo".charAt(0)
};
{
new $anon();
()
}
}
}
}
}
Use this method for problem:
x.getClass
If you are using IntelliJIDEA, to show Type Info action in Editor, navigate to the value and press Alt + = for Windows and Ctrl + Shift + P for Mac:
I find it very handy when writing code.
I've seen the args.foreach(arg => println(arg)), but when I search the doc http://www.scala-lang.org/api/current/index.html#scala.Array . I don't find it there and its companion object doc.
Any advice?
Thanks
Array gets operations such as foreach from scala.collection.mutable.ArrayOps - so you can lookup ArrayOps in the documentation to see what methods are available on arrays.
Predef contains a number of implicit conversion methods to make these available for arrays.
Unfortunately you can't see in the Scala API documentation for Array that these methods are available via the implicits in Predef.
As Jesper said, it's not really easy to find documentation on methods acquired via implicit conversions.
The ones defined for Array and the rationale behind them are explained here.
One (not particularly handy...) general way of finding out where a particular method comes from (in cases like yours, where it comes from an implicit conversion) is to use the -print option of the scala REPL.
If you run scala -print you will get:
scala> Array(1,2,3,4)
// ..... omitted for brevity
res0: Array[Int] = Array(1, 2, 3, 4)
scala> res0 foreach (println)
[[syntax trees at end of cleanup]]// Scala source: <console>
package $line2 {
final object $read extends java.lang.Object with ScalaObject {
def this(): object $line2.$read = {
$read.super.this();
()
}
};
#SerialVersionUID(0) final <synthetic> class $read$$iw$$iw$$anonfun$1 extends
scala.runtime.AbstractFunction1 with Serializable {
final def apply(x: java.lang.Object): Unit = scala.this.Predef.println(x);
final <bridge> def apply(v1: java.lang.Object): java.lang.Object = {
$read$$iw$$iw$$anonfun$1.this.apply(v1);
scala.runtime.BoxedUnit.UNIT
};
def this(): anonymous class $read$$iw$$iw$$anonfun$1 = {
$read$$iw$$iw$$anonfun$1.super.this();
()
}
};
final object $read$$iw$$iw extends java.lang.Object with ScalaObject {
private[this] val res1: scala.runtime.BoxedUnit = _;
<stable> <accessor> def res1(): Unit = ();
def this(): object $line2.$read$$iw$$iw = {
$read$$iw$$iw.super.this();
$read$$iw$$iw.this.res1 = {
scala.this.Predef.intArrayOps($line1.$read$$iw$$iw.res0()).foreach({
{
(new anonymous class $read$$iw$$iw$$anonfun$1(): Function1)
}
});
scala.runtime.BoxedUnit.UNIT
};
()
}
};
final object $read$$iw extends java.lang.Object with ScalaObject {
def this(): object $line2.$read$$iw = {
$read$$iw.super.this();
()
}
}
}
[[syntax trees at end of cleanup]]// Scala source: <console>
package $line2 {
final object $eval extends java.lang.Object with ScalaObject {
#volatile protected var bitmap$0: Int = 0;
<stable> <accessor> lazy def $result(): Unit = {
if ($eval.this.bitmap$0.&(1).==(0))
{
$eval.this.synchronized({
if ($eval.this.bitmap$0.&(1).==(0))
{
{
$eval.this.$print();
$line2.$read$$iw$$iw.res1()
};
$eval.this.bitmap$0 = $eval.this.bitmap$0.|(1);
()
};
scala.runtime.BoxedUnit.UNIT
});
()
};
()
};
private[this] val $print: java.lang.String = _;
<stable> <accessor> def $print(): java.lang.String = $eval.this.$print;
def this(): object $line2.$eval = {
$eval.super.this();
$eval.this.$print = {
$line2.$read$$iw$$iw;
""
};
()
}
}
}
1
2
3
4
If you look for .foreach inside this code, you will find the relevant line, that tells you the method is actually called on intArrayOps:
scala.this.Predef.intArrayOps($line1.$read$$iw$$iw.res0()).foreach(
In the accepted best response to this question, there is a clear explanation why boxing happens.
However, if I decompile the code (using java decompiler) I cannot see use of scala.runtime.BoxesRunTime. Furthermore, if I profile the code (using JProfiler) I cannot see any instances of BoxesRunTime.
So, how do I really see a proof of boxing/unboxing taking place?
In this code:
class Foo[T] {
def bar(i: T) = i
}
object Main {
def main(args: Array[String]) {
val f = new Foo[Int]
f.bar(5)
}
}
The invocation of bar should first box the integer. Compiling with Scala 2.8.1 and using:
javap -c -l -private -verbose -classpath <dir> Main$
to see the bytecode produced for the main method of the Main class yields:
public void main(java.lang.String[]);
...
9: iconst_5
10: invokestatic #24; //Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
13: invokevirtual #28; //Method Foo.bar:(Ljava/lang/Object;)Ljava/lang/Object;
16: pop
17: return
...
You can see the call to BoxesRunTime before the call to bar.
BoxesRunTime is an object which contains boxing methods for primitive types, so there should be exactly one instance in total. The trick here is that this particular file in the library was written in Java, and the conversions are static methods. For this reason there aren't any instances of it at runtime, although using it in Scala code feels as if it were an object.
You should probably look for boxed primitives (e.g. java.lang.Integer) with JProfile, though I am uncertain how the JVM works and whether it may actually rewrite the code at runtime and optimize it to avoid boxing. To my knowledge, it shouldn't apply specialization (but I believe CLR does). A few microbenchmarks with and without the boxing situation are another way to figure out what happens at runtime.
EDIT:
The above is assuming that a type parameter wasn't annotated with the #specialized annotation. In this case, the boxing/unboxing can be avoided. Certain classes in the standard library are specialized. See this sid.
Given the following Test.scala program:
object Test {
def main(args:Array[String]) {
val list = List(1,5,15)
val res = list.map(e => e*2).filter(e => e>10)
}
}
If I compile with scalac -Xprint:jvm Test.scala, I get this snippet suggesting that specialization occurs (sorry for wide paste):
package <empty> {
final class Test extends java.lang.Object with ScalaObject {
def main(args: Array[java.lang.String]): Unit = {
val list: List = immutable.this.List.apply(scala.this.Predef.wrapIntArray(Array[Int]{1, 5, 15}));
val res: List = list.map({
(new Test$$anonfun$1(): Function1)
}, immutable.this.List.canBuildFrom()).$asInstanceOf[scala.collection.TraversableLike]().filter({
(new Test$$anonfun$2(): Function1)
}).$asInstanceOf[List]();
()
};
def this(): object Test = {
Test.super.this();
()
}
};
#SerialVersionUID(0) #serializable final <synthetic> class Test$$anonfun$1 extends scala.runtime.AbstractFunction1$mcII$sp {
final def apply(e: Int): Int = Test$$anonfun$1.this.apply$mcII$sp(e);
<specialized> def apply$mcII$sp(v1: Int): Int = v1.*(2);
final <bridge> def apply(v1: java.lang.Object): java.lang.Object = scala.Int.box(Test$$anonfun$1.this.apply(scala.Int.unbox(v1)));
def this(): Test$$anonfun$1 = {
Test$$anonfun$1.super.this();
()
}
};
#SerialVersionUID(0) #serializable final <synthetic> class Test$$anonfun$2 extends scala.runtime.AbstractFunction1$mcZI$sp {
final def apply(e: Int): Boolean = Test$$anonfun$2.this.apply$mcZI$sp(e);
<specialized> def apply$mcZI$sp(v1: Int): Boolean = v1.>(10);
final <bridge> def apply(v1: java.lang.Object): java.lang.Object = scala.Boolean.box(Test$$anonfun$2.this.apply(scala.Int.unbox(v1)));
def this(): Test$$anonfun$2 = {
Test$$anonfun$2.super.this();
()
}
}
}
Could be why you don't see any evidence of boxing in bytecode...