在函數式語言中,函數是和value一樣地位的一等公民,他可以作為變量,或者作為參數傳遞給另一個函數
##作為變量
val f=(x:Int)=>x+1
為啥可以這樣寫?
由於scala是OOP,所以function也是個object。各個function都是繼承了Function類,比如Function1類表示參數是1的function類。




可見上述f是一個Function1的實例。所以作為實例的f有Function1的所有方法,其中有一個是apply方法,就是當f(1)的時候就會自動調用Function1的x+1這個方法。
這個時候怎么又來了個方法(method),函數和方法的區別是什么?
###function 和method的區別
可以說函數(function)是class,而method就是class中的一個函數(這個函數是指Java上的概念)。為啥呢,上面說了,各個function都是從Function繼承過來的,那么每個function都有一個特定的method,這個method是啥呢,就是能體現這個function真正作用的method,比如上面的就是x+1,只不過被Function類用apply包裝了。我們可以 想象成:
object myFunction extends Function1(){
...
apply(x:Int):Int=x+1
...
}
那么val f=(x:Int)=>x+1其實就是val f=new myFunction()
所以f(1)=f.apply(1)
所以,結論就是,函數的概念是大於方法的,函數其實本質是class,他是包含了方法的。
所以在理解了Function其實是class后,能很好的理解函數為什么可以作為變量了,其實f就是這個Function的一個實例而已。
###關於Function與method的轉換
method轉為Function


定義了一個g方法,那么如何將方法轉為函數呢
可以通過_來實現
val h=g _


這樣h就成了一個實例了。
>關於下划線_的作用
1. 作為“通配符”,類似Java中的*。如import scala.math._
2. :_*作為一個整體,告訴編譯器你希望將某個參數當作參數序列處理!例如val s = sum(1 to 5:_*)就是將1 to 5當作參數序列處理。
3. 指代一個集合中的每個元素。例如我們要在一個Array a中篩出偶數,並乘以2,可以用以下辦法:a.filter(_%2==0).map(2*_)。
又如要對緩沖數組ArrayBuffer b排序,可以這樣:
val bSorted = b.sorted(_
4. 在元組中,可以用方法_1, _2, _3訪問組員。如a._2。其中句點可以用空格替代。
5. 使用模式匹配可以用來獲取元組的組員,例如
val (first, second, third) = t
但如果不是所有的部件都需要,那么可以在不需要的部件位置上使用_。比如上一例中val (first, second, _) = t
6. 還有一點,下划線_代表的是某一類型的默認值。
對於Int來說,它是0。
對於Double來說,它是0.0
對於引用類型,它是null。
7. 用於將方法轉換成函數,比如val f=sqrt _,以后直接調用f(250)就能求平方根了
##作為參數傳遞


定義了一個fun方法,里面的參數有兩個一個是int型的x,一個是參數為int,返回值是int類型的函數f(感覺和C語言中的函數指針有點像)
那么如何往里面傳值呢,其實這里傳的還是一個變量,只是這個變量是Function的實例。上面分析了method可以轉換為Function,所以這里至少有兩種方法。
1. 直接傳一個變量,比如val m=(x:Int)=>x+1


接着


2. 傳一個方法(當然這個方法的參數和返回值需要滿足上述條件)


接着


這個能成功運行,說明這里有一個隱性的轉換機制。
>=>的作用
在Function中,表示將左邊的轉為右邊的
val triple=(x:Double)=>3*x
將函數作為參數
def fun(f:(Double)=>Double)=f(0.25)
這里表示fun函數接受一個f函數作為參數,這里的f類型是(Double)=>Double表示輸入為Double,輸出為Double的函數