一、作为值的函数
import scala.math._ val num = 3.14 val func = ceil _ // _意味着确实指的是这个函数,而不是忘记了传参数 ,func是一个函数变量,内容保存的是个函数 val v = func(num) println(v) val arr = Array(1.0,3.14,4).map(func) //将函数func传递给map方法,将他应用到数组中的所有值,然后返回结果数组 for(i<- arr) print(i+" ")
结果:
4.0 1.0 4.0 4.0
二、匿名函数
val func = (x:Double) => x*3 //匿名函数
val arr1 = Array(2.0,4,6).map((x:Double)=> x*3) //匿名函数 val arr2 = Array(2.0,4,6).map{(x:Double)=> x*3} //匿名函数,可以将函数用{}括起来 val arr3 = Array(2.0,4,6) map{(x:Double)=> x*3} //匿名函数,中置表示法,可以不用句号 for(i <- arr1) print(i+" ")
三、带函数参数的函数
import scala.math._ def valueAtFunc(f: (Double) => Double) = { // f: (Double) => Double 定义函数参数为 double,返回值为double f(0.25) //调用函数的参数为 2.0 } println(valueAtFunc(ceil _)) //将函数传递个 函数valueAtFunc println(valueAtFunc(sqrt _))
结果:
1.0 0.5
四、参数(类型)推断
import scala.math._ def valueAtFunc(f: (Double) => Double) = { // f: (Double) => Double 定义函数参数为 double,返回值为double f(0.25) //调用函数的参数为 2.0 } println(valueAtFunc(ceil _)) //将函数传递个 函数valueAtFunc println(valueAtFunc(sqrt _)) valueAtFunc((x:Double) => x*3 ) //匿名函数,指定类型 valueAtFunc((x)=>x*3) //匿名函数,已知参数类型 valueAtFunc(x=>x*3) //匿名函数,已知参数类型,去掉括号 valueAtFunc(_*3) //使用_替换 x val f1 = 3 * _ //错误,没指定类型 val f2 = 3 *(_:Double) //ok val f3:(Double)=>Double = 3 * _ // ok 指定了f3类型
匿名函数简写:
valueAtFunc((x:Double) => x*3 ) //匿名函数,指定类型
valueAtFunc((x)=>x*3) //匿名函数,已知参数类型
valueAtFunc(x=>x*3) //匿名函数,已知参数类型,去掉括号
valueAtFunc(_*3) //使用_替换 x
五、一些有用的高阶函数
map这个方法将一个函数应用到某个集合的所有元素并返回结果
foreach将函数应用到每个元素,并不返回结果
(0 to 9).map("*" * _).foreach(println(_))
结果:
* ** *** **** ***** ****** ******* ******** *********
filter输出所有匹配某个特定条件的元素
(0 to 9).filter(_ % 2 == 0).foreach(println(_))
结果:
0 2 4 6 8
reduceLeft方法接收一个二元函数,从左到右遍历元素
println((0 to 9).reduceLeft(_ + _)) // 相当于 (...((((0+1) + 2) + 3) + 4) ...+ 9)
结果
45
sortWith方法二元排序
"I am a bad guy".split(" ").sortWith(_.length<_.length).foreach(println(_))
结果:
I
a
am
bad
guy
六、闭包
闭包由代码和代码用到的非局部变量定义构成
七、SAM转换
Single Abstract Method
八、柯里化
Currying,指的是将原本接收两个参数的函数变成新的接收一个参数的函数的过程。
def mul(x:Int, y:Int) = x * y //接收两个参数的函数 def mulOneAtATime(x:Int) = (y:Int)=> x * y //接收一个参数的函数,需要接收两次参数 def mulOneAtATime1(x:Int)(y:Int) = x * y //柯里化 简写 println(mulOneAtATime(3)(4)) println(mulOneAtATime1(3)(4))
柯里化用途:
传递一个参数调用函数,有助于对参数类型进行推断,即类型推断
val a = Array("Hello","World") val b = Array("hello","world") a.corresponds(b)(_.equalsIgnoreCase(_))
Scaladoc说明
that是String类型的序列,所以第二个函数参数是(String, String) => Boolean,所以适用函数_.equalsIgnoreCase(_)传递两个String类型参数的函数。
九、控制抽象
实现类似while条件控制,柯里化实现
//until函数 类似于while def until(condition: => Boolean) (block: => Unit) { //不带参数,没有返回值的函数 block: => Unit if(condition){ block until(condition)(block) } } var x:Int = 10 until(x > 0){ //传递两个函数体, 第一个函数体当做条件,第二个函数体当做计算块 x -= 1 println(x) }
结果:
9 8 7 6 5 4 3 2 1 0
十、return表达式
//until函数 类似于while def until(condition: => Boolean) (block: => Unit) { //不带参数,没有返回值的函数 block: => Unit if(condition){ block until(condition)(block) } } var x:Int = 10 until(x > 0){ //传递两个函数体, 第一个函数体当做条件,第二个函数体当做计算块 x -= 1 println(x) } def indexOf(str: String, ch:Char): Int ={ var i = 0 until( i!=str.length){ if( str(i) == ch) return i //return 返回给带名函数,并不返回给匿名函数 {if(str(i) == ch) return i; i+=1}的until i+=1 } return -1 } println(indexOf("Hello", 'i'))
return在控制抽象中很有用。
参考《快学Scala》