我有几个与咖喱功能有关的问题。我在这里逐一问他们
1)http://twitter.github.com/scala_school/basics.html给出了一个curried函数的例子 - 我认为它是一个函数定义,但实际上并非如此。 REPL根本不承认这是一个有效的声明。
multiplyThenFilter { m: Int => m * 2 } { n: Int => n < 5}
2)为什么我们不能从部分参数化方法定义函数?即,以下定义有什么问题?
scala> def multiply(m: Int, n: Int): Int = m * n
multiply: (m: Int, n: Int)Int
scala> val timesTwo = multiply(2,_)
<console>:11: error: missing parameter type for expanded function ((x$1) => multiply(2, x$1))
val timesTwo = multiply(2,_)
^
3)为什么我们不能将部分参数化的功能用于咖喱?即,以下定义有什么问题?
scala> (multiply(_,_)).curried
res13: Int => (Int => Int) = <function1> // THIS IS OK
scala> (multiply(20,_)).curried
<console>:12: error: missing parameter type for expanded function ((x$1) => multiply(20, x$1))
(multiply(20,_)).curried
^
答案 0 :(得分:12)
Scala School示例 令人困惑 - 它绝对不是一个定义。在GitHub上有an issue开放,所以也许这是一个错误。您可以想象一个合理的定义可能如下所示:
def multiplyThenFilter(f: Int => Int)(p: Int => Boolean): Int => Option[Int] = {
i =>
val j = f(i)
if (p(j)) Some(j) else None
}
(或者,相当于f andThen (Some(_) filter p)
。)
然后该示例将是一个函数,它将其输入加倍并在Some
中返回结果,如果它小于5,否则返回None
。但是,在对该问题作出回应之前,没有人确切知道作者的意图。
您的timesTwo
不起作用的原因只是Scala编译器不支持这种类型推断 - 请参阅this question和my answer there了解一些相关细节。您需要使用以下其中一项:
def multiply(m: Int, n: Int): Int = m * n
val timesTwo = multiply(2, _: Int)
def multiply(m: Int)(n: Int): Int = m * n
val timesTwo = multiply(2) _
即,如果您想在此处进行类型推断,则需要使用多个参数列表。否则你必须使用类型帮助编译器。
对于您的第三个问题,假设我们在第二个问题中有以下内容以避免此问题:
val timesTwo = multiply(2, _: Int)
这是一个Function1
,它没有curried
方法 - 您需要Function2
(或Function3
等)。
谈论用一个参数来讨论函数是没有意义的。 Currying接受一个带有多个参数的函数,并为您提供一个函数,它接受一个返回另一个函数的参数(它本身可能需要一个参数并返回另一个函数等)。