我正在通过Odersky的scala函数式编程课程。
scala中的 currying 函数定义样式是:
def f(arg1)(arg2)....(argn) = E
它被证明等同于
def f = (arg1 => (arg2 => ...(argn => E)...))
根据课程。
令我困惑的是,为什么这个功能定义不起作用?
def sumOf(f: Int => Int)(a: Int, b: Int): Int = {
if (a > b) 0 else f(a) + sumOf(f)(a + 1, b)
}
// doesn't compile
def sumOfDouble = sumOf(x => x * 2)
由于 js 等其他语言的常见情况:
const sum = fn => (a, b) => (a > b) ? 0 : fn(a) + sum(fn)(a + 1, b);
const sumOfDouble = sum(x => x * 2);
sumOfDouble(1, 10); // => 110
让我更加困惑的是:
def sumbOf =
(f: Int => Int) =>
(a: Int, b: Int) =>
(
if (a > b) 0 else f(a) + sumbOf(f)(a + 1, b)
)
// this works
def sumOfDouble = sumbOf(x => x * 2)
sumOfDouble(1, 10) // => 110
那么在这里发生了什么,这两种形式的定义似乎并不相同?
如果是,那有什么区别?
答案 0 :(得分:3)
您的推理是正确的,但def
方法与函数值不完全等效:def
是方法,而不是类型为X => Y
的值。
Scala编译器确实会将未应用的方法提升为函数值,但仅限于预期的值。这意味着编译器必须确保这个"转换为函数值"是你所期待的。只要您提供显式类型,它就会无缝地发生。例如,您将sumOf(x => x * 2)
传递给另一个期望(Int, Int) => Int
的方法。在您声明sumOfDouble
的情况下,您只需要更明确一些,以下示例就可以正常运行:
// Explicit lifting into a function value
def sumOfDouble = sumOf(x => x * 2)(_, _)
// Explicit type to "force" the conversion
def sumOfDouble: (Int, Int) => Int = sumOf(x => x * 2)
// shorthand for the 1st example, but works for any number of parameters
def sumOfDouble = sumOf(x => x * 2) _
答案 1 :(得分:1)
def sumOfDouble = sumOf(x => x * 2)
在这种情况下,您只将方法应用于一个参数,但该方法需要两个。如果只想应用一个并将其用作匿名函数,则可以将其作为参数传递给高阶函数。请参阅modN
函数here
def sumOfDouble = sumbOf(x => x * 2)
这是有效的,因为它返回一个接受函数的函数,并返回一个接受两个参数的函数,并将该方法应用于这些参数。
在这种情况下,第一种情况是currying,而第二种情况与higher order functions
更密切相关希望这会有所帮助。如果你不明白,请回复。