scala混合了物件導向和函式式的特性。在函式式程式語言裡,函式是「頭等公民」,也就是說函式很重要,它可以像任何其他資料型別一樣被傳遞和操作。也就是說,函式可以作為乙個值傳給乙個變數。
在scala中,函式是「頭等公民」,就和數字一樣。可以在變數中存放函式:
val a = ceil _
val b = sqrt _
當然前提是匯入相應的包。這樣我們可以和ceil的用法一樣使用a。
a
(3.14)
匿名函式,也就是只有函式體,我們可以把它存放到變數中來使用:
val triple = (x : double) =>
3 * x
我們在一些經常使用到的函式裡面經常用到匿名函式,比如:map,reduceleft,reduceright,foldleft,foldright等這些函式中,我們經常要傳入一些我們為了滿足需求定義的一些函式或者匿名函式,比如:
(1 to 10)map((x : int) => x * 3)
將序列1到10的每個數字乘以3
這些都不是高階函式,只是為高階函式而服務的。
面向函式式程式設計的一大特點就是可以將函式作為引數,函式可以產生另乙個函式。
看一下這個函式:
def mulby(fun : (double) => double) = (x : double) => x * fun(2)
分析下這個函式,函式引數為乙個名為fun的函式,fun引數型別為double,返回值為double,mulby的返回值為乙個函式,因為這個函式的返回值為double所以mulby得型別為((double)=>double) => double)
scala中的引數型別推斷是scala的一格特色。
引數型別推斷
當你將乙個匿名函式傳遞給另乙個函式或方法時,scala會盡可能幫助你推斷出型別信,比如:
fun((x :double) => 3 * x)
可以寫成這樣:
fun(x => x * 3)
終極模式:
fun
(3 * _)
在scala有很多非常有用的高階函式,使用它們會讓你的**變得非常簡單,常見的有:map、reduceleft、foldleft、foldright、filter等等,都可一幫我們把我們的**簡化,我們來看一下用法:
1.map
map[b](f: (a) ⇒ b): list[b]
傳入乙個引數型別為a返回值為b的函式將集合中的每個元素經過這個函式的處理並將結果返回。
(1
to10)map(_* )
2.reduceleft
reduceleft[b >: a](f: (b, a) ⇒ b): b
該方法接受乙個二元函式,即帶有兩個引數的函式 — 並將它們用到序列中的所有元素,結合是從左往右的。
我們要求出給定序列中最大的值
val arr = array(2,11,3,42,5,62,4)
arr reduceleft((a,b)=> if(a > b) a else b)
就是說將乙個集合中的每兩個元素應用到reduceleft引入的函式中,返回滿足條件的結果。
3.reduceright
reduceright[b >: a](op: (a, b) ⇒ b): b
與reduceleft的用法一樣,不過集合中值是從右往左應用reduce中的函式。
4.foldleft
def
foldleft[b](z: b)
(op: (b, a) => b): b =
兩個引數,乙個型別為b的引數,另乙個返回值型別為b的函式作為引數,這個函式的的引數有兩個。
在reduceleft中,對集合中的元素處理的時候是從集合的開始處理的,在foldleft中,我們可以從指定的位置開始。
(1
to10) foldleft(2)(_*_)
從2開始做乙個壘乘。
5.foldright
def
foldright[b](z: b)
(op: (a, b) => b): b =
reversed.foldleft(z)((x, y) => op(y, x))
reversed操作
protected[this] def reversed =
foldright從源**可以看出是先將集合逆序然後在呼叫foldleft。
6.filter和字面意思一樣,主要作用是過濾掉一些不必要的元素。
(1
to10)filter (_%2 == 0)
閉包:有**和**用到的任何非區域性變數定義構成。
看下如下過程:
val triple = mulby(3)
val half = mubly(0.5)
println(triple(14) + " " + half(14))
可以這樣理解,乙個函式在執行過程中需要乙個區域性變數來完成這個操作,如上,我們每次都需要乙個factor值,這個factor是只屬於這個函式自己的,每次定義時使用的不一樣。這樣就形成了乙個閉包。
指的是將原來接受兩個引數的函式變成新的接受乙個引數的函式的過程。新的函式返回乙個以原有第二個引數作為引數的函式:
val
fun = (x : int) = (y : int) = x * y
用的時候可以這樣:
fun(3)(5)返回15
其實是先返回乙個函式(y : int) = 3 * y,然後再帶入5
乙個典型的應用:corresponds函式,原始碼
def
corresponds[b](that : seq[b])
(p : (a,b) => boolean) : boolean
兩個引數乙個型別為b的序列和乙個返回值為boolean的前提函式p。
例子:
val a = array("asd","abcd","amds")
val b = array(3,4,4)
val c = array(3,2,4)
println(a.corresponds(b)(_.length == _))
println(a.corresponds(c)(_.length == _))
scala學習筆記(十一) 高階函式
scala 作為函式式語言,函式自然是頭等公民 乙個接收函式作為引數的函式稱為高階函式 比如定義如下 defvalueatonequarter f double double f 0.25 這個函式接收乙個引數為 double 返回值為 double 的函式作為引數。高階函式還可以是返回乙個函式作為...
Scala高階函式
在scala中,無法直接操縱方法,只能直接操縱函式,所以需要使用 import scala math.val temp ceil val num 3.14 println fun temp num temp的型別是 double double,意為接受double引數並返回double的函式。能夠對...
Scala 高階函式
import scala.math.val num 3.14val func ceil 意味著確實指的是這個函式,而不是忘記了傳引數 func是乙個函式變數,內容儲存的是個函式 val v func num println v val arr array 1.0,3.14,4 map func 將函...