函数参数中没有LHS的“双右箭头类型”是什么意思

时间:2016-10-25 17:29:42

标签: scala

我无法解释指定为函数参数的“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 decompilationfooqux提供相同的定义时,scala如何区分这两者;以及barbaz

1 个答案:

答案 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,第二个被懒惰地评估。“