Edit Page

returnとジャンプ

Kotlinには3つの構造的ジャンプ演算子があります。

  • return. デフォルトでは最近のクロージャ(関数閉包)や匿名関数から抜け出します。
  • break 最も近い外側のループを終わらせます。
  • continue. 最も近い外側のループである次のステップに進みます。

breakとcontinueのラベル

Kotlinにおける任意の式を labelでマークすることができます。ラベルは、たとえば、 @ 記号に続く識別子の形式を持っています: abc@fooBar@が有効なラベル(文法を参照してください)です。式にラベルを付けるには、式の前にラベルを置きましょう:

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

さあ、これで私たちは breakcontinue をラベル付けできるようになりました:

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

ラベル付き break はそのラベルが付いたループの右後の実行ポイントへジャンプします。 continue はそのループの次の繰り返し実行(イテレーション)まで進みます。

ラベルに復帰する

Kotlinでは、関数リテラル、ローカル変数、オブジェクト式を使用すると、関数を入れ子にすることができます。 ある条件付きの returnを使うと、外側の関数から復帰することができます。 最も重要なユースケースは、ラムダ式からのreturnです。これを書くとき、思い出してください:

fun foo() {
  ints.forEach {
    if (it == 0) return
    print(it)
  }
}

return 式は最も内側の関数、すなわち foo から復帰します。 (このような非局所的復帰がインライン関数に渡されたラムダ式でのみサポートされていることに注意してください。) もしラムダ式から復帰する必要がある場合は、それにラベルを付け、 return を修飾する必要があります:

fun foo() {
  ints.forEach lit@ {
    if (it == 0) return@lit
    print(it)
  }
}

これはラムダ式からのみ復帰します。多くの場合、暗黙のラベルを使用する方が便利です。 そのようなラベルは、ラムダが渡された関数と同じ名前を持っています。

fun foo() {
  ints.forEach {
    if (it == 0) return@forEach
    print(it)
  }
}

代わりの手法として、無名関数とラムダ式を置き換えることができます。 無名関数内の return 文は、その無名関数自体から復帰します。

fun foo() {
  ints.forEach(fun(value: Int) {
    if (value == 0) return
    print(value)
  })
}

値を返すとき、パーサは資格を持つreturnを優先します。すなわち、

return@a 1

上記は「 @a ラベルにおけるreturn 1 」を意味し、「 (@a 1) ラベルが付いた式からのreturn」ではありません。