returnとジャンプ
Kotlinには、3つの構造的なジャンプ式があります。
return
は、デフォルトで最も近い囲んでいる関数または匿名関数から戻ります。break
は、最も近い囲んでいるループを終了します。continue
は、最も近い囲んでいるループの次のステップに進みます。
これらの式はすべて、より大きな式の一部として使用できます。
val s = person.name ?: return
これらの式の型は、Nothing型です。
breakとcontinueのラベル
Kotlinのどのような式でも、_ラベル_でマークできます。 ラベルは、abc@
やfooBar@
のように、識別子に@
記号を続けた形式をとります。 式にラベルを付けるには、その前にラベルを追加するだけです。
loop@ for (i in 1..100) {
// ...
}
これで、break
またはcontinue
をラベルで修飾できます。
loop@ for (i in 1..100) {
for (j in 1..100) {
if (...) break@loop
}
}
ラベルで修飾されたbreak
は、そのラベルが付けられたループの直後の実行ポイントにジャンプします。 continue
は、そのループの次のイテレーションに進みます。
returnのラベル
Kotlinでは、関数リテラル、ローカル関数、およびオブジェクト式を使用して関数をネストできます。 修飾されたreturn
を使用すると、外側の関数から戻ることができます。
最も重要なユースケースは、ラムダ式からの戻りです。ラムダ式から戻るには、それにラベルを付け、return
を修飾します。
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()
}
これにより、ラムダ式からのみ戻ります。多くの場合、そのようなラベルはラムダが渡される関数と同じ名前を持つため、_暗黙のラベル_を使用する方が便利です。
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
文は、匿名関数自体から戻ります。
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
に直接相当するものはありませんが、別のネストされたラムダを追加し、そこから非ローカルに戻ることでシミュレートできます。
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
を優先します。
return@a 1
これは、「ラベル@a
で1
を返す」という意味であり、「ラベル付き式(@a 1)
を返す」という意味ではありません。
NOTE
特定の場合では、ラベルを使用せずにラムダ式から戻ることができます。そのような非ローカルなreturnは、ラムダ内にありますが、囲んでいるインライン関数を終了します。