为什么柯里化函数的这个函数定义在 Scala 中不起作用?
Why this function definition from a curried function doesn't work in scala?
我正在学习 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
那么这里发生了什么,这两种形式的定义似乎并不等同?
如果是,有什么区别?
你的推理是正确的,除了 def
方法不完全等同于函数值:def
是一个方法,而不是 X => Y
.[=17 类型的值=]
Scala 编译器确实会将未应用的方法提升为函数值,但只有在需要这样的值时才会这样做。这意味着编译器必须确保此 "conversion to function value" 是您所期望的。只要您提供明确的类型,它就会无缝地发生。例如,这就是您将 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) _
def sumOfDouble = sumOf(x => x * 2)
在这种情况下,您只将该方法应用于一个参数,但该方法需要两个参数。如果只想应用一个并将其用作匿名函数,则可以将其作为参数传递给高阶函数。参见 modN
函数 here
def sumOfDouble = sumbOf(x => x * 2)
这是有效的,因为它 returns 一个接受函数的函数和 returns 一个接受两个参数并将该方法应用于这些参数的函数。
在这种情况下,第一种情况是柯里化,而第二种情况与 higher order functions
更密切相关
希望这对您有所帮助。不明白的请回复
我正在学习 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
那么这里发生了什么,这两种形式的定义似乎并不等同?
如果是,有什么区别?
你的推理是正确的,除了 def
方法不完全等同于函数值:def
是一个方法,而不是 X => Y
.[=17 类型的值=]
Scala 编译器确实会将未应用的方法提升为函数值,但只有在需要这样的值时才会这样做。这意味着编译器必须确保此 "conversion to function value" 是您所期望的。只要您提供明确的类型,它就会无缝地发生。例如,这就是您将 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) _
def sumOfDouble = sumOf(x => x * 2)
在这种情况下,您只将该方法应用于一个参数,但该方法需要两个参数。如果只想应用一个并将其用作匿名函数,则可以将其作为参数传递给高阶函数。参见 modN
函数 here
def sumOfDouble = sumbOf(x => x * 2)
这是有效的,因为它 returns 一个接受函数的函数和 returns 一个接受两个参数并将该方法应用于这些参数的函数。
在这种情况下,第一种情况是柯里化,而第二种情况与 higher order functions
更密切相关希望这对您有所帮助。不明白的请回复