Kotlin Lambda 與高階函式
Kotlin 是 函數式程式語言 (Functional Programming) 的擁護者。 這意味著函式是 一等公民 (First-class citizen):可以被存成變數、當作參數傳遞、也可以當作回傳值。
Lambda 表達式
Lambda 就是一個「沒有名字的函式」。
語法:{ 參數 -> 程式本體 }
val sum = { x: Int, y: Int -> x + y }
println(sum(1, 2)) // 3
高階函式 (Higher-Order Functions)
接受函式當作參數,或是回傳一個函式的函式,就叫高階函式。 最常見的例子就是集合操作常用的 filter、map。
val numbers = listOf(1, 2, 3, 4, 5)
// 把 lambda 傳給 filter
val evens = numbers.filter { it % 2 == 0 }
唯一的參數 (it)
如果 Lambda 只有一個參數,可以省略參數宣告 x ->,直接用 it 代表那個參數。
// 完整寫法
numbers.map { x -> x * 2 }
// 簡寫 (推薦)
numbers.map { it * 2 }
尾隨 Lambda (Trailing Lambda)
如果函式的 最後一個參數 是函式,你可以把 Lambda 把移到括號外面。
// 定義 High-Order Function
fun logic(n: Int, operation: (Int) -> Int) {
println(operation(n))
}
// 呼叫方式 1
logic(5, { it * it })
// 呼叫方式 2 (推薦:尾隨寫法)
logic(5) {
it * it
}
你看,這是不是很像在寫一個語言本身的語法結構?Android 的 Jetpack Compose 就是大量使用這種寫法。
函式型別 (Function Type)
變數可以存函式,那變數的型別是什麼?格式為 (參數型別) -> 回傳型別。
val onClick: () -> Unit = { println("Clicked") }
val sum: (Int, Int) -> Int = { a, b -> a + b }
Closure (閉包)
Kotlin 的 Lambda 可以存取並「修改」外部的變數(Java 的 Lambda 只能存取 final 變數)。
var sum = 0
numbers.filter { it > 0 }.forEach {
sum += it // 直接修改外部變數
}
println(sum)