Scala里的函数是一个“头等函数”(first-class value)。像其他的值,函数可以被当成参数传递,也可以被当成结果返回。这种情况下的函数被称为“高阶函数”(higher-order functions)
5.1 匿名函数(anonymous functions)
匿名函数就是没有名字的函数。例如:(x : Int , y : Int) => x * y 。这里有一点要注意:在实际写代码的时候,如果在 “=>”前加上了这个函数的返回类型,如:(x:Int , y : Int) : Int => x * y,反而会报错。原因是:在一般情况下,Scala编译器会自动推断匿名函数参数的类型,所以可以省略返回类型,因为返回类型对于编译器而言,是多余的。当然,如果匿名函数的参数只有一个,那么也可以把它的类型省略掉。
匿名函数并不是Scala语言中的必要元素(essential elements)。实际上,匿名函数可以如下等价:
(x1: T1 , ... , xn : Tn) => E
<=>
{def f(x1 : T1 , ... , xn :Tn) = E ; f _}
在这里的函数名f,不能在代码里其他地方使用。我们也通常说匿名函数是一个“语法糖”(syntactic sugar)
5.2 柯里化(currying)
以下面的代码为例:
def sum(f :Int => Int) : (Int , Int) => Int = { def sumF(a : Int , b : Int) : Int = if (a >b ) 0 else f(a) + sumF( a + 1 , b) sumF }
在这个形式中,sum是一个返回另一个函数的函数,被返回的函数名为sumF。现在这个函数也能完成之前的函数的工作,它可以带a,b两个参数,应用sum的参数f 到a和b之中,然后把它们加起来得到结果。
使用刚刚定义的函数,可以用def做如下定义:
def sumInts = sum(x => x) def sumSquares = sum( x => x * x) def sumPowersOfTwo = sum(powerOfTwo)
或者也可以做值定义:
val sumInts = sum( x => x) val sumSquares = sum( x => x * x) val sumPowersOfTwo = sum(powerOfTwo)
这么定义之后,就可以像使用内置的函数一样使用它们:
scala > sumSquares(1 , 10) +sumPowersOfTwo(10 , 20)
因为这种情况很常见,所以在Scala里有特殊的语法来实现它。下面有个例子:
def sum(f : Int => Int)(a : Int , b : Int) : Int = if ( a > b ) 0 else f(a) + sum(f)(a + 1 , b )
5.3 找到fixed points 。就是用一种递归的方式来找到这个固定点。类似于之前的求平方根的例子。其实从例子可以看出,柯里化可以对一个函数进行深层的抽象,这个便于代码复用。
5.4 总结
从之前的章节可以知道函数是必需的抽象,因为它允许我们引入计算的通用方法。而这个章节展示了这些抽象可以被组合成为高阶函数,来创造更深层的抽象。作为程序员,我们应该去寻找机会做抽象和代码复用。最高可能的抽象并不一定是最好的,但是知道抽象技术是很重要的事,所以应该在合适的地方使用抽象。
5.5 到现在为止看到的语法元素
之后就是讲一些类型(type),定义(definitions)等等。这些在《Scala编程》中也有讲过。属于基本的内容。略过。