为什么第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
}
}
答案 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_
为了使分配成功,所以method
是lifted
成为一个函数。
出于同样的原因,在你的代码中,
val f1 = multiply(1)
不起作用,因为编译器发现multiply(1)
的结果是您尝试分配给变量的方法,因此要求您按照说明添加_
在上述情况下。