[毎日Kotlin] Day37. Extension function literals

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

毎日Kotlinシリーズです。

このシリーズを初めての方はこちらです。「毎日Kotlin」はじめました | Developers.IO

問題

Function literals with receiver | Try Kotlin

Read about function literals with receiver.

You can declare isEven and isOdd as values, that can be called as extension functions. Complete the declarations below.

fun task(): List<Boolean> {
    val isEven: Int.() -> Boolean = { TODO() }
    val isOdd: Int.() -> Boolean = { TODO() }

    return listOf(42.isOdd(), 239.isOdd(), 294823098.isEven())
}

狙い

ここで考えて欲しい問題の意図はなんだろうか?

今日からDSLの章に突入!Kotlinの豊かな表現力を体感しましょう。

いろんな書き方ができるので、読みやすい、意図が伝わりやすい、書きやすい表現にしましょう。

解答例

fun task(): List<Boolean> {
    val isEven: Int.() -> Boolean = { this % 2 == 0 }
    val isOdd: Int.() -> Boolean = { this % 2 == 1 }

    return listOf(42.isOdd(), 239.isOdd(), 294823098.isEven())
}

isOdd()は記法だけみるとfunかなっと思うのですが、実は無名関数のオブジェクトなんですね。

fun task()内に定義してあるのでfun task()だけで使えます。

別解: fun

素直に実装するならfunで書きますね。

fun isEven(x: Int) = x % 2 == 0

fun isOdd(x: Int) = x % 2 == 1

fun task(): List<Boolean> {
    return listOf(isOdd(42), isOdd(239), isEven(294823098))
}

別解: 拡張関数

ちょっと便利に呼び出せるように、拡張関数にするのもありですね。

fun task(): List<Boolean> {
    return listOf(42.isOdd(), 239.isOdd(), 294823098.isEven())
}

fun Int.isEven() = this % 2 == 0
fun Int.isOdd() = this % 2 == 1

この関数内のみでつかえるようにしたいなら、関数内で定義することも可能です。

fun task(): List<Boolean> {
    fun Int.isEven() = this % 2 == 0
    fun Int.isOdd() = this % 2 == 1
    
    return listOf(42.isOdd(), 239.isOdd(), 294823098.isEven())
}

別解: 拡張プロパティ

拡張プロパティの書き方もできます。

val Int.isEven: Boolean
    get() = this % 2 == 0

val Int.isOdd: Boolean
    get() = this % 2 == 1


fun task(): List<Boolean> {
    return listOf(42.isOdd, 239.isOdd, 294823098.isEven)
}

あとがき

Day38.でまたお会いしましょう。