[2023] Kotlin チュートリアル
記事ディレクトリ
パート II オブジェクト指向プログラミングと関数型プログラミング
第 13 章 関数型プログラミングの基礎 — 高階関数とラムダ式
関数型プログラミングの考え方はオブジェクト指向と同じくらい古いものですが、関数型プログラミングをサポートするコンピューター言語が登場したのはごく最近のことです。これらの言語には、Swift、Python、Java 8、および C++ 11 が含まれます。新しい言語として、Kotlin は関数型プログラミングもサポートします。
13.4 クロージャとキャプチャ変数
Closure (クロージャ) は, 関数本体の外の変数にアクセスできる特別な関数です. この変数は, 元のスコープを離れても関数とともに存在します. このような特別な関数は、通常、ローカル関数、匿名関数、または Lambda 式です。
クロージャーは関数本体の外側の変数にアクセスできます。このプロセスは変数のキャプチャーと呼ばれます。サンプルコードは次のとおりです。
// 全局变量
var value = 10
fun main() {
// 局部变量
var localValue = 20
var result = {
a: Int ->
value++
localValue++
val c = a + value + localValue
println(c)
}
result(30) // 62
println("localValue = " + localValue) // 21
println("value = " + value) // 11
}
この例のクロージャは、value 変数と localValue 変数をキャプチャする Lambda 式です。変数 value と localValue を Lambda 本体にキャプチャします。
【Java プログラマー向けのヒント】Java では、Lambda 式がローカル変数をキャプチャする場合、ローカル変数は final しか使用できません。Lambda 本体では、ローカル変数のみを読み取ることができますが、ローカル変数を変更することはできません。Kotlin ではそのような制限はなく、ローカル変数は読み取りと変更が可能です。
[注意] クロージャが変数をキャプチャした後、これらの変数は特別なコンテナに格納されます。これらの変数が宣言された元のスコープが存在しなくなった場合でも、クロージャー本体は引き続きこれらの変数にアクセスできます。
ローカル関数の例を次に示します。
fun makeArray(): (Int) -> Int {
var ary = 0
// 局部函数捕获变量
fun add(element: Int): Int {
ary += element
return ary
}
return ::add
}
fun main() {
val f1 = makeArray()
println("---f1---")
println(f1(10))
println(f1(20))
println(f1(30))
}
ary 変数のスコープは makeArray 関数の本体であり、ローカル関数 add の本体では、変数 ary の値が変更されて返されます。
このように、main 関数内で呼び出した場合、f1 はローカル関数 add の変数であり、f1 が呼び出されるたびに ary の変数スコープが存在しなくなるため、ary 変数を保持できることに注意してください。
この栗は無名関数で実装することもできます。コードは次のとおりです。
fun makeArray(): (Int) -> Int {
var ary = 0
// 局部函数捕获变量
return fun(element: Int): Int {
ary += element
return ary
}
}
fun main() {
val f1 = makeArray()
println("---f1---")
println(f1(10))
println(f1(20))
println(f1(30))
}
makeArray 関数は Lambda 式を返します。Lambda 式を無名関数およびローカル関数と比較すると、Lambda 式のコードが最も簡潔であり、最終結果はまったく同じであることがわかります。