在函数式编程中,函数可以像任何其他数据类型一样被传递和操作。把明细动作包在函数中作为参数传入。
这篇文章包含如下主要内容:
1.可以创建匿名函数,并把匿名函数交给其他函数。
2.许多集合方法都接受函数参数,将函数应用到集合中的值。
3.可以创建操作代码块的函数,它们看上去像是内建的控制语句。
1.作为值的函数:
可以在变量中存放函数。并且可以对函数做两件事情:
(1)调用它
(2)传递它,存在一个变量中,或者作为参数传递给另一个函数。
下面的例子展示了对函数做的上边这2种操作:
/** * 1.作为值的函数,可以对函数做两件事情:(1)调用它;(2)传递它,将函数传递给另外一个函数。 */ import scala.math._ val pi = 3.14 //将函数传递给一个变量, 可以写成:ceil _ 或者 ceil(_) val fun = ceil _ //调用函数 println(fun(pi)) //传递函数 val output_array = Array(1.34,9.984,23.4).map { fun } println(output_array.mkString(","))
2.匿名函数:
在scala中,不需要为每一个函数命名,下面是一个匿名函数。 可以将匿名函数传给变量,或者直接将匿名函数传给另外一个函数。
/** * 2.匿名函数 */ //把匿名函数传给一个变量 val noname_func = (x:Double) => 3*x //把匿名函数传给另外一个函数 val output_array2 = Array(1.34,9.984,23.4).map { (x:Double) => 3*x } println(noname_func(2.32)) println(output_array2.mkString(","))
3.带函数参数的函数:
实现接受另一个函数作为参数的函数。如下面定义的函数:
def valueAtOneQuarter( f:(Double) => Double ) = f(0.25)
函数valueAtOneQuarter的参数是任何可以接受Double并返回Double的函数。valueAtOneQuarter的参数类型是 一个带有单个参数的函数,写作 (参数类型) => 结果类型 。
valueAtOneQuarter的类型可以写成是:((Double) => Double) => Double
由于valueAtOneQuarter是一个接受函数参数的函数,因此被称为“高阶函数”(higher-order function)。
高阶函数可以产生另一个函数。例如下边例子中的multBy函数:
/** * 3.带函数参数的函数 * 写一个能产出能够乘以任何数额的函数 * */ println("------------------测试:带函数参数的函数-----------------------") //这里的参数可以是任何接收Double并返回Double的函数。 def valueAtOneQuarter( f:(Double) => Double ) = f(0.25) def multBy(factor:Double) = (x:Double) => x*factor val testmul = multBy(4) println(testmul(8))
我们可以分析出multBy函数的类型是:
(Double) => ((Double) => Double)
4.参数推断:
当你把一个匿名函数传给另一个函数或方法时,Scala会推断出类型信息。
valueAtOneQuarter( (x:Double) => 3*x )
由于Scala可以推断出传给valueAtOneQuarter函数的参数类型是: (Double) => Double ,所以:Double完全可以省略。简化成:
valueAtOneQuarter( (x) => 3*x )
当匿名函数的参数只有一个时,可以省略括号,那么可以进一步简化为:
valueAtOneQuarter( x => 3*x )
如果参数在=>右侧只出现一次,可以用_替换掉它,进一步简化为:
valueAtOneQuarter(3*_)
5.一些常用的高阶函数:
(1) map函数:将函数应用到集合的每一个元素,并返回结果。
(2) foreach函数:foreach 和 map 很像,只不过它的函数不返回任何值。foreach只是简单地将函数应用到每一个元素。
(3) filter函数:输出所有匹配某个特定条件的元素。
(4) reduceLeft函数: 接受一个二元的函数(即:带有2个参数的函数),并将它应用到序列中的所有元素,从左到右。它和reduce的区别是,reduceLeft顺序是固定的(从左到右),但是reduce是没有顺序的(随机的)。
下面代码包含以上4个函数:
/** * 4.一些常用的高阶函数的使用 */ println("------------------测试:一些常用的高阶函数的使用-----------------------") //将1到9的一个集合每个都乘3 println(1.to(9).map{ 3*_ }) //foreach使用 1.to(9).map("*" * _).foreach{println _} //filter只取符合条件的值 println(1.to(9).filter {_ % 2 == 0 }) // 或者filter{ x => x % 2 == 0 } //reduceLeft接收一个二元函数,两个下划线分别是2个参数。 println(1.to(9).reduceLeft(_ + _))
6 .闭包:
对于返回的2个函数:trible 和 half ,它们都有自己各自的设置。trible的factor是3,half的factor是0.5。
那么对于multBy函数,每一个它返回的函数都有各自的factor设置,这样的函数叫做闭包。这些函数实际是以类的方式实现的,该类有一个实例变量factor和一个包含了函数体的apply方法。
/** * 5.闭包 * */ println("------------------测试:闭包-----------------------") val trible = multBy(3) val half = multBy(0.5) println(trible(18) + " " + half(18))
7.柯里化:
柯里化:指的是将原来接受2个参数的函数变成新的接受一个参数的函数的过程。新的函数返回一个以原有第二个参数作为参数的函数。