我无法解释指定为函数参数的“double-rightarrow Type”而没有LHS(左手边),例如() => Int
来自()
到Int
,但=> Int
是什么意思?
例如请参阅下面foo
方法的第一个参数,f
的类型是什么?是(Int, () => Int) => Int
吗?
对于bar
的定义,其中y按名称传递,我将其解释为一个没有参数的函数,它将生成一个Int,它看起来等同于baz
的定义。 / p>
我可以尝试推断f
中的foo
将第二个参数作为名称调用,而不是来自() => Int
,但这与bar
的事实相矛盾和baz
定义在javap中是相同的。我错过了什么?
object ParamTest {
def foo(f: (Int, => Int) => Int, x: Int) : Int = 10
def bar(x: Int, y: => Int) : Int = 20
def baz(x: Int, f: () => Int) : Int = 30
def qux(f: (Int, () => Int) => Int, x: Int) : Int = 40
}
为了测试我用scalac ParamTest.scala
javap ParamTest
给了我:
public final class ParamTest {
public static int qux(scala.Function2<java.lang.Object, scala.Function0<java.lang.Object>, java.lang.Object>, int);
public static int baz(int, scala.Function0<java.lang.Object>);
public static int bar(int, scala.Function0<java.lang.Object>);
public static int foo(scala.Function2<java.lang.Object, scala.Function0<java.lang.Object>, java.lang.Object>, int);
}
这似乎表明foo和qux具有相同的方法签名。换句话说,我可以将=> Int
解释为() => Int
,但是
foo(baz,100)
给出了类型不匹配错误
scala> import ParamTest._
import ParamTest._
scala> foo(bar,100)
res0: Int = 10
scala> foo(baz,100)
<console>:11: error: type mismatch;
found : (Int, () => Int) => Int
required: (Int, => Int) => Int
foo(baz,100)
^
编辑:这与this question不同。我不是在问call-by-name: => Type
和() => Type
之间的实际区别。我知道的更有趣的是内部。当javap或cfr decompilation为foo
和qux
提供相同的定义时,scala如何区分这两者;以及bar
和baz
。
答案 0 :(得分:4)
正如您所发现的,() => A
和=> A
不是一回事。
按名称呼叫(即=> A
)只是意味着:“延迟对此方法参数的评估。”换句话说,懒惰的评价。
def f(x: Int, y: => Int) = ???
f(3+5, 2+4)
在此示例中,在呼叫站点添加3 + 5并且x
值为8.另一方面,在{{1}之前不会再添加2 + 4在方法y
的主体内引用。如果该引用位于未执行的f()
分支中,则永远不会进行添加。
对于像if...else...
这样的简单评估来说,这是毫无意义的,但如果参数是一个昂贵的评估,如果它是一个带有副作用的代码块,它就会变得更有意义。
所以,在回答你的问题时,Int
的意思是:“{{1}}有两个参数并产生一个f: (Int, => Int) => Int
,参数是2 f
s,第二个被懒惰地评估。“