Skip to content

returnとジャンプ

Kotlinには、3つの構造的なジャンプ式があります。

  • returnは、デフォルトで最も近い囲んでいる関数または匿名関数から戻ります。
  • breakは、最も近い囲んでいるループを終了します。
  • continueは、最も近い囲んでいるループの次のステップに進みます。

これらの式はすべて、より大きな式の一部として使用できます。

kotlin
val s = person.name ?: return

これらの式の型は、Nothing型です。

breakとcontinueのラベル

Kotlinのどのような式でも、_ラベル_でマークできます。 ラベルは、abc@fooBar@のように、識別子に@記号を続けた形式をとります。 式にラベルを付けるには、その前にラベルを追加するだけです。

kotlin
loop@ for (i in 1..100) {
    // ...
}

これで、breakまたはcontinueをラベルで修飾できます。

kotlin
loop@ for (i in 1..100) {
    for (j in 1..100) {
        if (...) break@loop
    }
}

ラベルで修飾されたbreakは、そのラベルが付けられたループの直後の実行ポイントにジャンプします。 continueは、そのループの次のイテレーションに進みます。

NOTE

特定の場合では、明示的にラベルを定義しなくても、breakcontinue非ローカルに適用できます。

そのような非ローカルな使用は、囲んでいるインライン関数で使用されるラムダ式で有効です。

returnのラベル

Kotlinでは、関数リテラル、ローカル関数、およびオブジェクト式を使用して関数をネストできます。 修飾されたreturnを使用すると、外側の関数から戻ることができます。

最も重要なユースケースは、ラムダ式からの戻りです。ラムダ式から戻るには、それにラベルを付け、returnを修飾します。

kotlin
fun foo() {
    listOf(1, 2, 3, 4, 5).forEach lit@{
        if (it == 3) return@lit // ラムダの呼び出し元(forEachループ)へのローカルreturn
        print(it)
    }
    print(" done with explicit label")
}

fun main() {
    foo()
}

これにより、ラムダ式からのみ戻ります。多くの場合、そのようなラベルはラムダが渡される関数と同じ名前を持つため、_暗黙のラベル_を使用する方が便利です。

kotlin
fun foo() {
    listOf(1, 2, 3, 4, 5).forEach {
        if (it == 3) return@forEach // ラムダの呼び出し元(forEachループ)へのローカルreturn
        print(it)
    }
    print(" done with implicit label")
}

fun main() {
    foo()
}

あるいは、ラムダ式を匿名関数に置き換えることもできます。 匿名関数内のreturn文は、匿名関数自体から戻ります。

kotlin
fun foo() {
    listOf(1, 2, 3, 4, 5).forEach(fun(value: Int) {
        if (value == 3) return  // 匿名関数の呼び出し元(forEachループ)へのローカルreturn
        print(value)
    })
    print(" done with anonymous function")
}

fun main() {
    foo()
}

前の3つの例でのローカルreturnの使用は、通常のループでのcontinueの使用に似ていることに注意してください。

breakに直接相当するものはありませんが、別のネストされたラムダを追加し、そこから非ローカルに戻ることでシミュレートできます。

kotlin
fun foo() {
    run loop@{
        listOf(1, 2, 3, 4, 5).forEach {
            if (it == 3) return@loop // runに渡されたラムダからの非ローカルreturn
            print(it)
        }
    }
    print(" done with nested loop")
}

fun main() {
    foo()
}

値を返す場合、パーサーは修飾されたreturnを優先します。

kotlin
return@a 1

これは、「ラベル@a1を返す」という意味であり、「ラベル付き式(@a 1)を返す」という意味ではありません。

NOTE

特定の場合では、ラベルを使用せずにラムダ式から戻ることができます。そのような非ローカルなreturnは、ラムダ内にありますが、囲んでいるインライン関数を終了します。