我在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)
如何扩展?
提前致谢。
答案 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
的每个部分应用都会导致为它创建一个新类。另一方面,给定两个参数时效率较低,因为始终会创建闭包。