リターンとジャンプ
Kotlinには3つの構造的なジャンプ式(jump expressions)があります。
return: デフォルトでは、最も内側の囲んでいる関数または匿名関数から戻ります。break: 最も内側の囲んでいるループを終了します。continue: 最も内側の囲んでいるループの次のステップに進みます。
これらの式はすべて、より大きな式の一部として使用できます。
val s = person.name ?: returnこれらの式の型はNothing型です。
Breakとcontinueのラベル
Kotlinの任意の式にはラベル(label)を付けることができます。 ラベルは、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 は、そのループの次のイテレーション(反復)に進みます。
場合によっては、ラベルを明示的に定義せずに 非局所的(non-locally)に
breakやcontinueを適用できることがあります。このような非局所的な使用法は、囲んでいるインライン関数で使用されるラムダ式内で有効です。
ラベルへのリターン
Kotlinでは、関数リテラル、ローカル関数、オブジェクト式を使用して関数をネストできます。 ラベル指定された return を使用すると、外側の関数から戻ることができます。
最も重要なユースケースは、ラムダ式からのリターンです。ラムダ式から戻るには、ラベルを付けて return を修飾します。
fun foo() {
listOf(1, 2, 3, 4, 5).forEach lit@{
if (it == 3) return@lit // ラムダの呼び出し元(forEachループ)への局所的なリターン
print(it)
}
print(" done with explicit label")
}
fun main() {
foo()
}これにより、ラムダ式からのみ戻るようになります。多くの場合、暗黙的なラベル(implicit labels)を使用する方が便利です。そのようなラベルは、ラムダが渡される関数と同じ名前になります。
fun foo() {
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return@forEach // ラムダの呼び出し元(forEachループ)への局所的なリターン
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ループ)への局所的なリターン
print(value)
})
print(" done with anonymous function")
}
fun main() {
foo()
}前述の3つの例における局所的なリターンの使用は、通常のループにおける continue の使用に似ていることに注意してください。
break に直接相当するものはありませんが、外側に run ラムダを追加し、そこから非局所的にリターンすることでシミュレートできます。
fun foo() {
run loop@{
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return@loop // runに渡されたラムダからの非局所的なリターン
print(it)
}
}
print(" done with nested loop")
}
fun main() {
foo()
}ここでの非局所的なリターンは、ネストされた forEach() ラムダがインライン関数として動作するため可能です。
値を返す際、パーサーはラベル指定されたリターンを優先します。
return@a 1これは「ラベル @a に 1 を返す」という意味であり、「ラベル付きの式 (@a 1) を返す」という意味ではありません。
場合によっては、ラベルを使用せずにラムダ式から戻ることができます。このような 非局所的(non-local)なリターンは、ラムダ内に配置されますが、それを囲んでいるインライン関数を終了します。
