My other question got closed as a duplicate, so I'll try this again. I have also read this question and what I'm asking is different. I'm interested in learning the internal implementation of how Call-by-Name: => Type
differs from () => Type
.
My confusion is coming from looking at javap and cfr disassembly which shows no difference in the two cases.
e.g. ParamTest.scala:
object ParamTest {
def bar(x: Int, y: => Int) : Int = if (x > 0) y else 10
def baz(x: Int, f: () => Int) : Int = if (x > 0) f() else 20
}
javap output javap ParamTest.scala
:
public final class ParamTest {
public static int baz(int, scala.Function0<java.lang.Object>);
public static int bar(int, scala.Function0<java.lang.Object>);
}
CFR Decompiled output java -jar cfr_0_118.jar ParamTest$.class
:
import scala.Function0;
public final class ParamTest$ {
public static final ParamTest$ MODULE$;
public static {
new ParamTest$();
}
public int bar(int x, Function0<Object> y) {
return x > 0 ? y.apply$mcI$sp() : 10;
}
public int baz(int x, Function0<Object> f) {
return x > 0 ? f.apply$mcI$sp() : 20;
}
private ParamTest$() {
MODULE$ = this;
}
}
EDIT 1:
Scala Syntax Tree: scalac -Xprint:parse ParamTest.scala
package <empty> {
object ParamTest extends scala.AnyRef {
def <init>() = {
super.<init>();
()
};
def bar(x: Int, y: _root_.scala.<byname>[Int]): Int = if (x.$greater(0))
y
else
10;
def baz(x: Int, f: _root_.scala.Function0[Int]): Int = if (x.$greater(0))
f()
else
20
}
}
EDIT 2: Mailing list research:
Read this interesting post on the mailing list which essentially states that => T
is implemented as () => T
. Quote:
First, look at
f: => Boolean
Although this is called a "by-name parameter", it is actually implemented as a
Function0
,
f: () => Boolean
just with different syntax used on both ends.
Now I'm even more confused by this answer which explicitly states that the two are different.
Questions:
- How is Scala distinguishing
bar
frombaz
? The method signatures (not implementation) for both are identical in the decompiled code. - Does the difference in the two scenarios not get persisted into the compiled bytecode?
- Is the decompiled code inaccurate?
- Added after Edit 1: I found that the scalac syntax tree does show a difference,
bar
has the second argument of type_root_.scala.<byname>[Int]
. What does it do? Any explanation, pointers in scala source or equivalent pseudo code will be helpful. - See EDIT 2 above: Is the quoted block correct? As in, is
=> T
a special subclass ofFunction0
?