我正在学习更多关于Scala的知识,我在http://www.scala-lang.org/node/135中理解匿名函数的例子时遇到了一些麻烦。我已经复制了下面的整个代码块:
object CurryTest extends Application {
def filter(xs: List[Int], p: Int => Boolean): List[Int] =
if (xs.isEmpty) xs
else if (p(xs.head)) xs.head :: filter(xs.tail, p)
else filter(xs.tail, p)
def modN(n: Int)(x: Int) = ((x % n) == 0)
val nums = List(1, 2, 3, 4, 5, 6, 7, 8)
println(filter(nums, modN(2)))
println(filter(nums, modN(3)))
}
我对modN功能的应用感到困惑
def modN(n: Int)(x: Int) = ((x % n) == 0)
在示例中,使用一个参数
调用它modN(2) and modN(3)
modN(n:Int)(x:Int)的语法是什么意思?
由于它是用一个参数调用的,我假设它们不是两个参数,但我无法弄清楚如何使用mod函数来使用nums的值。
答案 0 :(得分:46)
这在名为currying的函数式编程中是一件有趣的事情。基本上MosesSchönfinkel和后者Haskell Curry(Schonfinkeling虽然听起来很奇怪......)想出了调用多个参数函数的想法,比如f(x,y)
与调用链{g(x)}(y)
相同或者g(x)(y)
其中g
是一个产生另一个函数作为输出的函数。
例如,使用函数f(x: Int, y: Int) = x + y
。正如预期的那样,对f(2,3)
的调用会产生5
。但是当我们讨论这个函数时会发生什么 - 将其重新定义为f(x:Int)(y: Int)
并将其称为f(2)(3)
。第一个调用f(2)
生成一个带整数y
并向其添加2
的函数 - >因此f(2)
的类型为Int => Int
,相当于函数g(y) = 2 + y
。第二个调用f(2)(3)
使用参数g
调用新生成的函数3
,因此按预期评估为5
。
查看它的另一种方法是逐步减少(函数式程序员称之为beta-reduction - 就像逐行逐步的功能性方式)f(2)(3)
调用(注意,以下内容并非如此)有效的Scala语法)。
f(2)(3) // Same as x => {y => x + y}
|
{y => 2 + y}(3) // The x in f gets replaced by 2
|
2 + 3 // The y gets replaced by 3
|
5
因此,在所有这些讨论之后,f(x)(y)
可以被视为以下lambda表达式(x: Int) => {(y: Int) => x + y}
- 这是有效的Scala。
我希望这一切都有道理 - 我试图给出一些为什么 modN(3)
调用有意义的背景:)
答案 1 :(得分:3)
答案 2 :(得分:2)
在该示例中,modN 返回一个由特定N修改的函数。它使您无需执行此操作:
def mod2(x:Int): Boolean = (x%2) == 0
def mod3(x:Int): Boolean = (x%3) == 0
两对parens分隔您可以停止向方法传递参数的位置。当然,即使方法只有一个参数列表,你也可以使用占位符来实现相同的功能。
def modN(n: Int, x: Int): Boolean = (x % n) == 0
val nums = List(1, 2, 3, 4, 5)
println(nums.filter(modN(2, _)))
println(nums.filter(modN(3, _)))