Мой другой вопрос закрыт как дубликат, поэтому я попробую это снова. Я также прочитал этот вопрос, и то, что я прошу, отличается. Мне интересно изучить внутреннюю реализацию того, как Call-by-Name: => Type
отличается от () => Type
.
Моя путаница исходит из рассмотрения javap и cfr разборки, которая не показывает разницы в двух случаях.
например. 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 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 Декомпилированный вывод 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;
}
}
РЕДАКТИРОВАТЬ 1:
Scala Дерево синтаксиса: 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
}
}
ИЗМЕНИТЬ 2: Исследование рассылки:
Прочитайте этот интересный пост в списке рассылки, который по существу утверждает, что => T
реализован как () => T
. Цитата:
Во-первых, посмотрите
f: => Boolean
Хотя это называется "параметром по имени", он фактически реализуется как
Function0
,
f: () => Boolean
просто с различным синтаксисом, используемым на обоих концах.
Теперь меня еще больше смущает этот ответ, в котором явно указано, что они разные.
Вопросы
- Как Scala отличить
bar
отbaz
? Сигнатуры метода (а не реализации) для обоих идентичны в декомпилированном коде. - Различия в двух сценариях не сохраняются в скомпилированном байт-коде?
- Является ли декомпилированный код неточным?
- Добавлено после редактирования 1: я обнаружил, что дерево синтаксиса scalac показывает разницу,
bar
имеет второй аргумент типа_root_.scala.<byname>[Int]
. Что оно делает? Любое объяснение, указатели в Scala source или эквивалентный псевдокод будут полезны. - См. EDIT 2 выше: Правильно ли указан кавычек? Как и в, есть
=> T
специальный подклассFunction0
?