当我只将一个参数传递给curried函数时,为什么编译成功?

时间:2016-04-04 05:40:07

标签: scala

为什么第8行编译成功而第15行没有编译?这两行代码之间的区别是什么?

package test

object TestCurrying {

  def multiply(x: Int)(y: Int): Int = x * y

  def invoke(f: Int => Int => Int): Int = {
    val f1 = f(1) //Compile success
    f1(2)
  }

  def main(args: Array[String]) {
    val res = invoke(multiply)

    val f1 = multiply(1)//Compile fail
  }
}

2 个答案:

答案 0 :(得分:0)

tpolecat对gitter的解决,非常感谢他。以下是他的好回答:

  

这里有一些事情发生。您可以将方法转换为   通过η-扩展起作用。表达式乘法_将给你一个   Int =>类型的函数值Int =>委托给方法的Int。   在期望这种函数类型的上下文中,编译器将   为你做这件事。这就是你说的时候发生的事情   调用(乘)。你可以部分地应用一个curried函数   很好,正如你在f(1)中看到的那样。你不能用curried方法做到这一点   (除非在预期会出现这种类型的情况下);你会的   需要说乘(1)_

     

乘(1):( Int => Int)然而,因为归属   为编译器提供有关预期类型的​​更多信息。

答案 1 :(得分:0)

这个问题的答案在于方法和功能之间的区别。尽管如此,它与currying没什么关系。

现在multiply是一种方法。当我们将方法传递给另一个方法(在这种情况下为invoke)时,它会自动lifted到一个函数。这个lifting是通过eta扩展完成的。 Scala方法是类的一部分。它有一个名字,一些身体的签名。 Scala中的函数是一个完整的对象。 Scala中有一系列特征来表示具有各种参数的函数:Function0,Function1,Function2等。 查看更多详情here

scala提供的将方法转换或提升为函数的方法是_运算符。

假设您有方法

 def testMethod(n:Int){
//insert code here
}

你有一条线

val testf = testMethod(4) 

这一行意味着calling方法testMethod。 但是,如果我写,

val testf = testMethod

这意味着我没有调用或调用方法,而是将方法分配给变量testf。这个assignment操作意味着我们的意思是将该方法视为function即。一个完整的,完整的实体。编译器会抱怨上述行,并建议您向_添加testMethod

出于这个原因我们需要写,   val testf = testMethod_ 为了使分配成功,所以methodlifted成为一个函数。 出于同样的原因,在你的代码中,

val f1 = multiply(1)不起作用,因为编译器发现multiply(1)的结果是您尝试分配给变量的方法,因此要求您按照说明添加_在上述情况下。

相关问题