这一篇是单独讲函数的高级特性,因为scala的精髓就是函数式编程,而函数式编程的精髓就在于他的高级特性。话不多说,直奔主题。
1. 匿名函数
匿名函数可以说是高级特性的基础,很多奇技淫巧都构建在他的基础之上。匿名函数即lambda表达式,基于数学中的λ演算得名(这里面有更深奥的数学理论,有兴趣可以去研究一下)。匿名函数的书写形式如下:
(x:Int) => {x+1}
也可以用一个变量来接收这个匿名函数:
var func= (x:Int) => {x+1}
然后就可以像这样调用:
var result = func(7)-1
你可以尽情发挥你的想象,把匿名函数放在几乎你想放的任何地方。它的好处是”不污染环境“,什么意思自己体会。这就是lambda表达式的神奇之处。
作为函数的参数你可以这样:
def func(fc:(T)=>Boolean)={} //定义一个接收函数的参数
func((i)=>{if(i>5) true}) //调用这个函数,传进去一个匿名函数
匿名函数的自动参数推断能帮我们简化很多,事实上自动推断也是scala编译器最牛叉的一个特性,在很多地方都会用到,其中一个就是隐式转换,我会在另一篇中讲到,回到这里:
一般使用匿名函数的一个标准写法是:
object Test{
def main(args:Array(String)){
var array=Array(1,2,3,4)
var square=array.map((a:Int)=>2*a)
println(square.mkString(","))
}
}
但是编译器知道array里面是Int型数值,故可以省去类型限定:
object Test{
def main(args:Array(String)){
var array=Array(1,2,3,4)
var square=array.map((a)=>2*a)
println(square.mkString(","))
}
}
object Test{
def main(args:Array(String)){
var array=Array(1,2,3,4)
var square=array.map(a => 2*a)
println(square.mkString(","))
}
}
object Test{
def main(args:Array(String)){
var array=Array(1,2,3,4)
var square=array.map( _ * 2)
println(square.mkString(","))
}
}
2.函数柯里化(currying)
将原来接受多个参数的函数变成接受一个参数的过程。例:
def add(x:Int,y:Int)=x+y //普通的相加函数
def add(x:Int)(y:Int)=x+y //柯里化函数
add(1)(2)
柯里化实现原理:
def add(x:Int)=(y:Int)=>x+y
val result=add(1) //add函数的返回值是一个匿名函数,x被实例化,y还是这个匿名函数的参数
val sum=result(2)
3.闭包
闭包是可以保存每一次函数调用状态的函数,普通函数是没有状态的。闭包是由函数和环境组成,它使得函数内部的变量即使脱离了函数的作用范围依然可以访问到。例:
def increase():()=>Int={
var count=0
()=>{count+=1; count}
}
var res=increase()
println("first:"+res())
println("second:"+res())
可以敲出来试一下看结果是什么。当然这只是闭包最简单的一种用法,更多用法读者可以自行发挥想象。
4.高阶函数
scala的精华所在,就是可以操作其他函数的函数。可以使用其他函数作为参数,或者作为一个对象调用另一个函数,或者返回一个函数对象。例:
object Test{
def main(args:Array(String)){
println(apply(layout,10))
}
def apply(f:Int=>String,v:Int)=f(v)
def layout[A](x:A)="["+x.toString()+"]"
}
返回一个函数对象:
object Test{
def main(args:Array(String)){
println(area(2.2)())
}
def area(r:Double)=()=>{Math.PI*r*r}
}
5. 特性总结
(未完待续...)