Kotlinにおける関数型とラムダ式

関数型

val functionCall = func() と書くと関数を呼び出してその戻り値を取得しますが、
val functionCall = ::func と書くと関数そのものを参照します。

ラムダ

構文形式を確認する

ラムダ構文

関数をデータ型として扱う

戻り値の型を指定しなければ、コンパイラは自動的に Unit を戻り値とみなします。
Kotlinでは、すべての関数は何かを返す必要があります。戻り値を指定しない場合、コンパイラは自動的に Unit () : () -> /型/ のように書くことで、関数の戻り値の型を明示的に指定したことになります。

さまざまな書き方の例:

fun main() {
    val refFunction = ::sampleFunction
    refFunction()
    
    val refLambda = sampleLambda
    refLambda()
    
    f2()
    
    createProcessor(name = "ProcessorA")(5)
}

fun sampleFunction(): () -> Unit {
    println("sampleFunction called!")
    return { println("Returned function from sampleFunction!") }
}

val sampleLambda = {
    println("sampleLambda called (val lambda)!")
}

val f2: () -> Unit = fun() {
    println("Anonymous function via lambda syntax")
}

// 引数で String を受け取り、「Int を受け取って Unit を返す関数」を返す
fun createProcessor(name: String): (Int) -> Unit {
    return { count ->
        println("$name は $count 個のタスクを処理しました")
    }
}
// なぜこのように二重の括弧(createProcessor(...)(...))を使うのか?
// より複雑な関数呼び出しを実現するためです。

入れ子の面白い例

fun trickOrTreat(isTrick: Boolean, extraTreat: ((Int) -> String)?): () -> Unit {
    // 実装省略
}

自然言語での説明

この関数は、isTrick という Boolean 引数と、関数を受け取ります。
渡される関数は Unit を返します(返される関数は引数をキャプチャしません)。
渡される関数は null 許容で、もし非 null であれば Int を受け取り String を返します。

スコープ外で it を使わない場合、明示的に引数名を指定する

fun main() {
    // quarters -> で引数に名前を付けている
    println(trickOrTreat(true) { quarters -> "$quarters quarters" })
    println(trickOrTreat(false) { quarters -> "$quarters quarters" })
    
    val quarters = 3
    println("$quarters quarters")
}

// ラムダ内でも quarters という名前にする必要がある
val treatFunction = trickOrTreat(false) { quarters -> "$quarters candies" }

fun trickOrTreat(isTrick: Boolean, treatFunction: (quarters: Int) -> String): String {
    return if (isTrick) "Trick!" else treatFunction(2)
}

通常は it を使って簡潔に書く:

fun main() {
    println(trickOrTreat(true) { "$it quarters" })
    println(trickOrTreat(false) { "$it quarters" })
}

val treatFunction = trickOrTreat(false) { "$it candies" }

fun trickOrTreat(isTrick: Boolean, treatFunction: (Int) -> String): String {
    return if (isTrick) "Trick!" else treatFunction(2)
}

例えば、以下の coin は削除可能:

fun main() {
    val coins: (Int) -> String = {
        "$it quarters"
    }
    val treatFunction = trickOrTreat(false, { "$it quarters" })
    val trickFunction = trickOrTreat(true, null)
    treatFunction()
    trickFunction()
}

タグ: Kotlin 関数型 ラムダ式 高階関数 関数参照

7月10日 16:21 投稿