Syntax 匿名Scala函数语法

Syntax 匿名Scala函数语法,syntax,scala,anonymous-function,Syntax,Scala,Anonymous Function,我正在学习更多关于Scala的知识,在理解中的匿名函数示例时遇到了一些困难。我复制了下面的整个代码块: 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)

我正在学习更多关于Scala的知识,在理解中的匿名函数示例时遇到了一些困难。我复制了下面的整个代码块:

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中的值。

在该示例中,modN返回一个函数,该函数按特定的N进行mods。这样做可以省去您的麻烦:

def mod2(x:Int): Boolean = (x%2) == 0
def mod3(x:Int): Boolean = (x%3) == 0
这两对参数限定了可以停止向方法传递参数的位置。当然,即使方法只有一个参数列表,也可以使用占位符来实现同样的效果

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, _)))

您正在部分应用ModN函数。部分函数应用是函数式语言的主要特征之一。有关更多信息,请查看这些关于和样式的文章。

这是函数式编程中的一件有趣的事情。基本上,摩西·舍芬克尔(Moses Schönfinkel)和后来的哈斯克尔·库里(Haskell Curry,Schonlinking听起来很奇怪……)提出了这样一个想法:调用多个参数的函数,比如
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)
调用新生成的带有参数
3
的函数
g
,因此计算结果与预期一致

查看它的另一种方法是逐步执行
f(2)(3)
调用的缩减(函数式程序员称之为beta缩减-类似于逐行执行的函数式缩减)(注意,以下不是真正有效的Scala语法)

因此,在所有这些讨论之后,
f(x)(y)
可以被看作是下面的lambda表达式
(x:Int)=>{(y:Int)=>x+y}
——这是有效的Scala


我希望这一切都是有意义的-我试着给出一点背景信息,说明为什么
modN(3)
调用有意义:)

感谢您的详细回复。在使用占位符的第二个示例中,您能否解释最后一个:Int是用于什么的,即:def modN(n:Int)(x:Int):Int与def modN(n:Int)(x:Int)是否只是占位符可以使用和不能使用时的语法差异,编译器抱怨modN的参数数量不正确,这是因为
modN(x,y)
不是调用函数的有效方式(Scala不自动进行无毛刺处理,即从
f(x)(y)
转换为
f(x,y)
)。因此,在本例中调用
modN
的正确方法是
modN(2)(41;
。另外,小的挑剔-返回类型
modN
不正确,它应该是
modN(n:Int)(x:Int):Boolean=(x%n)==0
。或者,您可以让类型推断器进行推断。:)我更新了第二个示例以减少错误。谢谢你的解释,弗拉维,解释得很好。我将您的更改为接受的答案(加上您修复了上一个示例中的错误)。从现在起我只使用这个词-D
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