匿名函数
Scala 中定义匿名函数的语法很简单,箭头左边是参数列表,右边是函数体。
使用匿名函数后,我们的代码变得更简洁了。
下面的表达式就定义了一个接受一个Int类型输入参数的匿名函数:
var inc = (x:Int) => x+1
上述定义的匿名函数,其实是下面这种写法的简写:
def add2 = new Function1[Int,Int]{ def apply(x:Int):Int = x+1; }
以上实例的 inc 现在可作为一个函数,使用方式如下:
var x = inc(7)-1
高阶函数
高阶函数是指使用其他函数作为参数、或者返回一个函数作为结果的函数。在Scala中函数是“一等公民”,所以允许定义高阶函数。这里的术语可能有点让人困惑,我们约定,使用函数值作为参数,或者返回值为函数值的“函数”和“方法”,均称之为“高阶函数”。
最常见的一个例子是Scala集合类(collections)的高阶函数map
val salaries = Seq(20000, 70000, 40000) val doubleSalary = (x: Int) => x * 2 val newSalaries = salaries.map(doubleSalary) // List(40000, 140000, 80000)
函数doubleSalary
有一个整型参数x
,返回x * 2
。一般来说,在=>
左边的元组是函数的参数列表,而右边表达式的值则为函数的返回值。在第3行,函数doubleSalary
被应用在列表salaries
中的每一个元素。
为了简化压缩代码,我们可以使用匿名函数,直接作为参数传递给map
:
val salaries = Seq(20000, 70000, 40000) val newSalaries = salaries.map(x => x * 2) // List(40000, 140000, 80000)
注意在上述示例中x
没有被显式声明为Int类型,这是因为编译器能够根据map函数期望的类型推断出x
的类型。对于上述代码,一种更惯用的写法为:
val salaries = Seq(20000, 70000, 40000)
val newSalaries = salaries.map(_ * 2)
既然Scala编译器已经知道了参数的类型(一个单独的Int),你可以只给出函数的右半部分,不过需要使用_
代替参数名(在上一个例子中是x
)
curry(柯里化)
多参数列表(柯里化):一个步骤掰成两个部分。
方法可以定义多个参数列表,当使用较少的参数列表调用多参数列表的方法时,会产生一个新的函数,该函数接收剩余的参数列表作为其参数。这被称为柯里化。
下面是一个例子,在Scala集合 trait TraversableOnce
定义了 foldLeft
def foldLeft[B](z: B)(op: (B, A) => B): B
foldLeft
从左到右,以此将一个二元运算op
应用到初始值z
和该迭代器(traversable)的所有元素上。以下是该函数的一个用例:
从初值0开始, 这里 foldLeft
将函数 (m, n) => m + n
依次应用到列表中的每一个元素和之前累积的值上。
val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) val res = numbers.foldLeft(0)((m, n) => m + n) print(res) // 55
PartialFunction(偏函数)
如果你想定义一个函数,而让它只接受和处理其参数定义域范围内的子集,对于这个参数范围外的参数则抛出异常,这样的函数就是偏函数(顾名思异就是这个函数只处理传入来的部分参数)。
def isDefinedAt(x: A): Boolean //作用是判断传入来的参数是否在这个偏函数所处理的范围内