ラムダ式
| 対応: | Kotlin 1.0(2016) |
|---|
Kotlinのラムダ式は『{ 引数 -> 処理 }』の形で書く無名関数です。引数が1つのときは『it』で参照でき、関数の最後の引数がラムダの場合は括弧の外に書く「末尾ラムダ」が使えます。
構文
// ラムダ式の基本形
val lambda = { x: Int -> x * 2 }
val result = lambda(5) // 10
// 引数なしのラムダ
val greet = { println("Hello!") }
// 引数が1つのとき it で参照できる
val double: (Int) -> Int = { it * 2 }
// 末尾ラムダ(最後の引数がラムダのとき括弧の外に書けます)
listOf(1, 2, 3).map { it * 2 }
listOf(1, 2, 3).filter { it > 1 }
// 複数行のラムダ(最後の式が戻り値になります)
val process = { x: Int ->
val doubled = x * 2
doubled + 1 // この式が戻り値
}
構文一覧
| 構文 | 概要 |
|---|---|
| { 引数: 型 -> 処理 } | ラムダ式の基本形です。 |
| it | 引数が1つのラムダで引数を参照するデフォルト名です。 |
| 末尾ラムダ | 最後の引数がラムダの場合、括弧の外に『{ }』を書けます。 |
| _ (アンダースコア) | 使わない引数を『_』で省略できます(Kotlin 1.1以降)。 |
| return@ラベル | ラムダ内での return にラベルを付けて外側の関数への return と区別します。 |
サンプルコード
sample_lambda_expression.kt
fun main() {
// ラムダ式の基本
val add = { a: Int, b: Int -> a + b }
println(add(3, 5)) // 8
// it を使う省略記法
val doubled = listOf(1, 2, 3, 4, 5).map { it * 2 }
println(doubled) // [2, 4, 6, 8, 10]
// 末尾ラムダ
val evens = listOf(1, 2, 3, 4, 5, 6).filter { it % 2 == 0 }
println(evens) // [2, 4, 6]
// 複数引数のラムダ
val pairs = listOf("a" to 1, "b" to 2, "c" to 3)
pairs.forEach { (key, value) -> // 分割宣言でラムダ引数を展開する
println("$key: $value")
}
// 使わない引数を _ で省略する
pairs.forEachIndexed { _, (key, _) ->
println(key)
}
// 複数行ラムダ(最後の式が戻り値)
val process: (Int) -> String = { n ->
val abs = if (n < 0) -n else n
val label = if (abs > 10) "large" else "small"
"$abs is $label"
}
println(process(-15)) // 15 is large
println(process(5)) // 5 is small
// return@ラベルでラムダから抜ける
val numbers = listOf(1, 2, 3, 4, 5)
numbers.forEach {
if (it == 3) return@forEach // ラムダのみ抜けます(continue相当)
println(it)
}
// 1, 2, 4, 5 が出力される
// ラムダを変数に格納して後で使う
val operations: List<(Int) -> Int> = listOf(
{ it * 2 },
{ it + 10 },
{ it * it }
)
println(operations.map { it(4) }) // [8, 14, 16]
}
lambda_expression.kt
kotlinc lambda_expression.kt -include-runtime -d lambda_expression.jar java -jar lambda_expression.jar 8 [2, 4, 6, 8, 10] [2, 4, 6] a: 1 b: 2 c: 3 a b c 15 is large 5 is small 1 2 4 5 [8, 14, 16]
よくあるミス
sample_lambda_mistakes.kt
fun main() {
// ラムダから外側の関数に return しようとして非 inline でエラー
// listOf(1, 2, 3).forEach { return } → コンパイルエラー(non-local return は inline 関数でのみ可)
// ラムダのみ抜けるには return@forEach を使う
listOf(1, 2, 3).forEach {
if (it == 2) return@forEach
println(it)
}
// 引数が複数あるのに it を使おうとする
// val pairs = listOf(1 to "one", 2 to "two")
// pairs.forEach { println(it.first) } // it は Pair 全体を指す(コンパイルは通るが意図が不明確)
// 明示的に引数名を付けると分かりやすい
val pairs = listOf(1 to "one", 2 to "two")
pairs.forEach { (num, word) -> println("$num: $word") }
// 複数行ラムダで return を書いてしまう
val process: (Int) -> String = { n ->
// return "$n!" → コンパイルエラー(ラムダ内の return は non-local return になる)
"$n!" // 最後の式が戻り値
}
println(process(5)) // 5!
// 型注釈なしで it を使おうとする
// val fn = { it * 2 } → コンパイルエラー(it の型が推論できない)
val fn: (Int) -> Int = { it * 2 }
println(fn(4)) // 8
}
コンパイルして実行すると次のようになります。
kotlinc sample_lambda_mistakes.kt -include-runtime -d sample_lambda_mistakes.jar java -jar sample_lambda_mistakes.jar 1 3 1: one 2: two 5! 8
概要
ラムダ式はKotlinのコレクション操作や高階関数の呼び出しに頻繁に使われます。引数が1つの場合は『it』で参照でき、末尾ラムダ構文を使うとコードが読みやすくなります。
ラムダ内で外側の関数に『return』したい場合は、『inline』関数でなければコンパイルエラーになります。ラムダのみ抜けたい場合は『return@forEach』のようにラベルを付けてください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。