Scala基礎(3) 函式高階

2021-08-27 20:07:52 字數 1665 閱讀 1443

函式可以沒有名稱,可以直接賦值。如果函式有多行表示式組成,就加上大括號。這一點對匿名函式同樣適用。

scala> val addone = (x: int) => x + 1

addone: (int) => int = scala> addone(1)

res4: int = 2

注意到scala中一切都是物件。所以addone是乙個物件。同時它又是個包含乙個引數的函式。此時,函式和物件得到了統一。

偏函式應用解決這樣的問題:如果我們有函式是多個引數的,我們希望能固定其中某幾個引數的值。在scala中,我們可以這麼做

scala> def adder(m: int, n: int) = m + n

adder: (m: int,n: int)int

scala> val add2 = adder(2, _:int)

add2: (int) => int = scala> add2(3)

res50: int = 5

偏函式應用不是什麼新東西,幾乎所有程式語言中都可以簡單地實現。但更簡潔的實現是柯里化。

你可以這樣定義柯里化 函式

scala> def multiply(m: int)(n: int): int = m * n

multiply: (m: int)(n: int)int

也可以對乙個已有的函式進行轉換。例如之前的adder函式

scala> (adder _).curried

res1: (int) => (int) => int =

函式柯里化依賴匿名函式,把乙個多引數的函式轉化為多個單引數的函式連線在一起。這樣一來,語意的表達就更加豐富而直觀,函式組合也更加靈活。

乙個應用場景就是型別推斷。scala類庫中的foldleft就是這樣乙個例子。

def foldleft[b](z: b)(op: (b, a) => b): b

list("").foldleft(0)(_ + _.length)

如果使用普通的多引數函式定義

def foldleft[b](z: b, op: (b, a) => b): b
那麼,你在使用時就必須顯示地表明型別。

list("").foldleft(0, (b: int, a: string) => a + b.length)

list("").foldleft[int](0, _ + _.length)

另乙個currying的應用是簡化api。在下面的例子中,你可以使用大括號來傳遞body,使得api呼叫層次分明。

def loop[a](n: int)(body: => a): unit = (0 until n) foreach (n => body)

loop(2)

如果你的多引數函式的計算實際上是分步驟的,某個步驟只依賴某個引數,比如下面的例子。那麼柯里化會更加簡單。

def v(t: double, k: double): double = 

v(1, 1); v(1, 2);

scala基礎3 函式

常規函式 def f x int int 無返回值,使用unit def f unit unit和其他型別都可以省略,scala可以執行判斷函式的返回型別 def f f def f print f 無返回值,可以省略,unit不能寫 def f 無參函式 def f println hello f...

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 將函...