免责声明:我对 Scala 还很陌生,所以请谨慎对待
在像 Haskell 这样的纯函数式语言中,柯里化在函数组合中起着非常重要的作用,例如,如果我想找到平方和,我会用 Haskell 编写(对不起,Haskell 太多了,但语法与 Scala 有相似之处,并不难猜)
没有咖喱:
sum_of_squares xs = foldl (\x y -> x + y) 0 (map (\x -> x * x) xs)
带有curring(.
是一个函数组合):
sum_of_squares = (foldl (\x y -> x + y) 0) . (map (\x -> x * x))
这使我可以使用函数而不是使用参数进行操作。前面的例子可能不太清楚,但考虑一下:
sum_of_anything f = (foldl (\x y -> x + y) 0) . (map f)
这f
是一个任意函数,我可以将第一个示例重写为:
sum_of_squares = sum_of_anything (\x -> x * x)
现在让我们回到 Scala。Scala 是面向对象的语言,所以通常xs
是一个接收者:
def sum_of_squares(xs: List[Int]): Int = {
xs.map(x => x * x).foldLeft(0)((x, y) => x + y)
}
sum_of_squares(List(1,2,3))
def sum_of_anything(f: (Int, Int) => Int)(xs: List[Int]): Int = {
xs.map(x => x * x).foldLeft(0)(f)
}
sum_of_anything((x, y) => x + y)(List(1, 2, 3))
这意味着我不能省略xs
. 我可能可以用 lambdas 重写它,但是如果不添加更多样板map
,我将无法使用。foldLeft
因此,正如其他人在 Scala 中提到的“currying”可能主要用于支持类型推断。
同时,在您的特定示例中,我感觉您不需要 outer a
,无论如何它都被遮住了,您可能的意思是:
def sum(b: Int) : (Int => Int) = {
def go(a: Int) : Int = {
a + b;
}
go
}
但是在这个简单的示例中,您可以使用部分应用程序(假设您可能会传递sum
给更高阶的函数):
List(1, 2, 3).map(sum(2)) //> res0: List[Int] = List(3, 4, 5)
List(1, 2, 3).map(_ + 2) //> res1: List[Int] = List(3, 4, 5)
对于这种应用程序sum
可以更短,因为sum(2)
将隐式扩展为Int => Int
:
def sum(b: Int)(a: Int): Int = a + b
但是,此表格无效val sum2 = sum(2)
,您必须写val sum2 = sum(2) _
.