言語
日本語
English

Caution

お使いのブラウザはJavaScriptが無効になっております。
当サイトでは検索などの処理にJavaScriptを使用しています。
より快適にご利用頂くため、JavaScriptを有効にしたうえで当サイトを閲覧することをお勧めいたします。

Kotlin辞典

  1. トップページ
  2. Kotlin辞典
  3. 単一式関数 / ローカル関数

単一式関数 / ローカル関数

対応: Kotlin 1.0(2016)

Kotlinでは関数が1つの式で完結する場合、中括弧と『return』を省略した「単一式関数」として書けます。また関数の中に関数を定義する「ローカル関数」で処理をスコープ内にカプセル化できます。

構文

// 通常の関数
fun double(x: Int): Int {
    return x * 2
}

// 単一式関数(= を使って簡潔に書けます)
fun double(x: Int): Int = x * 2

// 型推論で戻り値型も省略できます
fun double(x: Int) = x * 2

// ローカル関数(関数の中に関数を定義します)
fun process(numbers: List<Int>): List<Int> {
    fun validate(n: Int): Boolean = n > 0 // ローカル関数
    return numbers.filter { validate(it) }
}

構文一覧

構文概要
fun name(p) = 式単一式関数です。= の右辺がそのまま戻り値になります。
戻り値型の省略式から型が推論できる場合は戻り値型を省略できます。
ローカル関数関数の内部で定義する関数です。外側のスコープの変数にアクセスできます。
ネスト関数ローカル関数内でさらにローカル関数を定義できます。

サンプルコード

sample_single_expr_local_function.kt
// 単一式関数の例
fun square(n: Int) = n * n
fun greet(name: String) = "Hello, $name!"
fun isEven(n: Int) = n % 2 == 0
fun max(a: Int, b: Int) = if (a > b) a else b

// ローカル関数の例
fun findDuplicates(numbers: List<Int>): List<Int> {
    // ローカル関数 — 外側の変数 numbers にアクセスできます
    fun hasDuplicate(n: Int): Boolean =
        numbers.count { it == n } > 1

    return numbers.filter { hasDuplicate(it) }.distinct()
}

// ローカル関数で再帰を使う例
fun factorial(n: Int): Long {
    fun calc(x: Int, acc: Long): Long = // 末尾再帰用ローカル関数
        if (x <= 1) acc else calc(x - 1, acc * x)
    return calc(n, 1L)
}

fun main() {
    // 単一式関数の呼び出し
    println(square(5)) // 25
    println(greet("Kotlin")) // Hello, Kotlin!
    println(isEven(4)) // true
    println(max(10, 7)) // 10

    // ローカル関数の呼び出し
    val nums = listOf(1, 2, 3, 2, 4, 3, 5)
    println(findDuplicates(nums)) // [2, 3]

    // 階乗(ローカル関数による末尾再帰)
    println(factorial(5)) // 120
    println(factorial(10)) // 3628800

    // 単一式関数を組み合わせる
    fun cube(n: Int) = n * square(n) // square は上で定義した関数
    println(cube(3)) // 27
}
single_expr_local_function.kt
kotlinc single_expr_local_function.kt -include-runtime -d single_expr_local_function.jar
java -jar single_expr_local_function.jar
25
Hello, Kotlin!
true
10
[2, 3]
120
3628800
27

よくあるミス

sample_single_expr_local_function_mistakes.kt
// 複数文になる処理を単一式関数で書こうとする
// 単一式関数は式(expression)1つだけ書ける — 文(statement)は書けない
// fun setup(name: String) = { // ラムダを返す関数になってしまう
//     println("名前: $name") // これはラムダの中身
//     name.uppercase() // これも実行されない
// }
// 複数の処理が必要なときは通常の中括弧スタイルを使う

// ローカル関数を定義前に呼ぶ
fun computeScore(values: List<Int>): Int {
    // validate(0) // コンパイルエラー: ローカル関数は定義後しか使えない
    fun validate(n: Int) = n >= 0 // 定義はここ
    return values.filter { validate(it) }.sum()
}

// 単一式関数の戻り値が Unit になることを見落とす
// 式が Unit を返す場合は Unit が推論される
// 別の型を返すつもりで書いた場合、意図が伝わらずバグになる
fun printGreeting(name: String) = println("こんにちは、$name!")
// 戻り値は Unit(println が Unit を返すため)— 値を使おうとすると Unit になる

fun main() {
    println(computeScore(listOf(-1, 5, 3, -2, 8)))
    printGreeting("牧瀬紅莉栖")
    val ret = printGreeting("岡部倫太郎")
    println("戻り値: $ret") // 戻り値: kotlin.Unit
}

コンパイルして実行すると次のようになります。

kotlinc sample_single_expr_local_function_mistakes.kt -include-runtime -d sample_single_expr_local_function_mistakes.jar
java -jar sample_single_expr_local_function_mistakes.jar
16
こんにちは、牧瀬紅莉栖!
こんにちは、岡部倫太郎!
戻り値: kotlin.Unit

概要

単一式関数は『=』を使って1行で定義できるため、シンプルな変換関数やユーティリティ関数を簡潔に書けます。ただし処理が複雑になる場合は通常の中括弧スタイルのほうが読みやすいです。

ローカル関数は外側の関数の変数にアクセスできるクロージャです。外部から呼ばれない補助ロジックをローカル関数にまとめることで、スコープを外側の関数の内部に限定できます。同様の目的でラムダ式も使えますが、ローカル関数は再帰が書きやすいという利点があります。

基本的な関数定義はfun 関数の定義を、ラムダについてはラムダ式を参照してください。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。