Scala语法帮助Currying

时间:2014-06-06 16:18:10

标签: scala functional-programming currying

我在scala中遇到了类似这样的代码:

  def test1(f : Int => Int)(x : Int) = x + f(x)

  def test2(f : Int => Int)(x : Int) = f(x)

  test2(test1(x => 2*x))(2)

我很困惑,所以函数test1将一个函数和一个Int作为参数,并返回一个函数,对吗?那么test1(x => 2*x)如何有效并将函数返回给test2?显然它需要2作为整数参数,但为什么呢?声明test2(test1(x => 2*x))(2)如何扩展?

提前致谢。

2 个答案:

答案 0 :(得分:1)

  

function test1将一个函数和一个Int作为参数,并返回一个函数,对吗?

不,它只需要一个函数作为参数并返回一个函数。返回的函数然后将int作为参数并返回一个int。

  

那么test1(x => 2 * x)如何有效并将函数返回给test2?

我希望现在很清楚。

  

语句test2(test1(x => 2 * x))(2)如何扩展?

test1为参数调用

x => 2*x并返回一个函数。然后使用返回的函数作为其参数调用test2并返回另一个函数。然后用2作为参数调用其他函数。

答案 1 :(得分:0)

此:

test2(test1(x => 2*x))(2)

扩展到:

test2(y => test1(x => 2*x)(y))(2)
具有多个参数列表的Scala方法可以像其他语言中的curried函数一样工作,但事实上它们是作为需要所有参数的方法实现的,并且这确实在语法中显示出来。例如,如果你将它放入REPL:

test1(x => 2*x)

它会抱怨缺少论点。这种语法允许的是" eta-expansion",其中方法被转换为函数。如果你写:

val func: Int => Int = test1(x => 2*x) _

您可以获得代表test1部分应用的函数。如果上下文需要,Scala将自动进行eta扩展,这就是test2(test1(x => 2*x))(2)所发生的情况。请注意,test1本身永远不会返回函数,但编译器将在需要时基于它构建函数。

但是,如果您将test1定义为:

def test1(f : Int => Int) = (x : Int) => x + f(x)

然后编译器将接受test1(x => 2*x)而没有_。此外,在底层实现中,只有一个类实现由test1恢复的闭包,而对于原始定义,test1的每个部分应用都会导致为它创建一个新类。另一方面,给定两个参数时效率较低,因为始终会创建闭包。