내 other question이 복제물로 폐쇄되었으므로 다시 시도하겠습니다. 나는 또한 this question을 읽었으며 내가 묻는 것은 다르다. 나는 () => Type
과 다른 Call-by-Name: => Type
의 내부 구현을 배우는 데 관심이 있습니다.스칼라가() => T와 => T를 구별하는 방법 T
두 경우에 차이가없는 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 ParamTest.scala
은 javap 출력 :
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;
}
}
EDIT 1 : 스칼라 구문 트리 : 2scalac -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
}
}
편집 : 메일 링리스트의 연구 :
은 본질적으로 => T
는 () => T
로 구현되는 내용의 메일 링리스트에이 interesting post을 읽어보십시오. 인용구 :이가 "로 이름 매개 변수"라고되어 있지만
첫째, 그것은 실제로
Function0
로 구현,
f: => Boolean
볼
f:() => Boolean
양쪽 끝에 다른 구문이 사용되었습니다.
이제 두 개가 다른 것으로 명시된 this answer에 의해 더욱 혼란스러워집니다.
질문 :
- 어떻게 스칼라
baz
에서bar
을 구별합니까? 두 가지에 대한 메소드 서명 (구현이 아님)은 디 컴파일 된 코드에서 동일합니다. - 두 시나리오의 차이점이 컴파일 된 바이트 코드에 유지되지 않습니까?
- 디 컴파일 된 코드가 부정확합니까?
- 편집 한 후 : 나는 scalac 구문 트리가 차이를 보이지 않는 것으로,
- 위의 편집 2 참조 : 따옴표 붙은 블록이 맞습니까? 에서와 같이
=> T
Function0
의 특수 하위 클래스입니까?
bar
유형
_root_.scala.<byname>[Int]
의 두 번째 인수가 있습니다. 그것은 무엇을합니까?모든 설명, 포인터는
scala source 또는 이와 동등한 의사 코드가 유용합니다.
왜 이러한 유형이 JVM 바이트 코드로 표현 되는가가 중요한 이유는 무엇입니까? 그것들은 스칼라 코드가 다르다. 중요한 것은 (자바에서 스칼라를 호출하지 않는 한, 당신이 요구하는 것이 아니다). –
스칼라는 그런 식으로 작동하기 때문입니다. 스칼라 코드를 .class 파일로 컴파일하고 JVM에서 실행합니다. 따라서 .class 파일에는 필요하고 충분한 정보가 있어야합니다. 스칼라 소스 파일은 전혀 중요하지 않습니다. [연결된 질문] (http://stackoverflow.com/questions/40246137/what-does-double-right-arrow-type-with-no-lhs-mean-in-function-argument/)을 참조하십시오. 'ParamTest.scala' 소스 파일을 삭제 한 후'foo (baz, 100)'호출 오류. – vsnyc
이 질문에 대한 또 다른 동기는 [이 답변] (http://stackoverflow.com/a/13337382/2063026)입니다. 가장 인상 된 의견 (160)이 주장하는 바에 따르면, " '=> Int'는'Int'와는 다른 타입으로, Int를 생성하는 인자가없는 함수입니다. 그러나 우리가 위에서 보았 듯이 그것은 사실이 아닙니다. call-by-name은 게으른 평가와 관련이 있으며, 아무런 인자도없는 함수가 아닙니다 ... – vsnyc