Scala 中函數是一等公民。Function1[-T1, +R] 表示單參數函數,Function2[-T1, -T2, +R] 表示雙參數函數,均為 trait,核心方法為 apply。
val inc = new Function1[Int, Int] {
def apply(x: Int) = x + 1
}
println(inc.apply(5)) // 6
println(inc(5)) // 語法糖,等同 apply(5)
函數組合構建新函數:
f.andThen(g):先執行 f,結果傳給 g,即 g(f(x))f.compose(g):先執行 g,結果傳給 f,即 f(g(x))val f = (x: Int) => { println(s"f: $x"); x + 1 }
val g = (x: Int) => { println(s"g: $x"); x * 2 }
val h1 = f.andThen(g) // 先 f 後 g
println(h1(5))
// f: 5
// g: 6
// 12
val h2 = f.compose(g) // 先 g 後 f
println(h2(5))
// g: 5
// f: 10
// 11
val add = new Function2[Int, Int, Int] {
def apply(x: Int, y: Int) = x + y
}
println(add(1, 2)) // 3
// 柯裡化:(Int, Int) => Int 轉為 Int => (Int => Int)
val curried = add.curried
println(curried(1)(2)) // 3
// 元組化:(Int, Int) => Int 轉為 ((Int, Int)) => Int
val tupled = add.tupled
println(tupled((1, 2))) // 3
// 部分鍵用 val add5 = add.curried(5) // Int => Int println(add5(10)) // 15 // 管道式組合:數據流向清晰 val pipeline = (x: Int) => x * 2 .andThen(_ + 1) .andThen(_ * 3) .compose(_ - 1) println(pipeline(5)) // ((5-1)*2+1)*3 = 27
| 特性 | Function1 | Function2 |
|---|---|---|
| 類型參數 | 2個 | 3個 |
| 參數個數 | 1 | 2 |
| 柯裡化 | 不適用 | .curried |
| 元組化 | 不適用 | .tupled |
| 組合方向 | andThen/compose | 同樣支援 |
Scala 2.12+ 支援單抽象方法(SAM)類型自動轉換:
// Java 函數式介面自動轉換
val runnable: Runnable = () => println("Hello") // 隱式轉換
// Scala FunctionN 也是 SAM 類型
val f: Function1[Int, Int] = _ + 1 // 自動實現 apply