1. 序章

この記事では、breakステートメントをScalaで使用してループを終了する方法を示します。

break ステートメントは、 for while 、およびdo…whileループを停止できます。

2. フードの下

Scalaのbreakステートメントは言語機能ではなく、実装されたメソッドであるため、対応するループのコンテキストはありません。

break ステートメントが機能する方法は、例外をスローすることです。 breakable関数の実装を見てみましょう。

def breakable(op: => Unit) {
  try {
    op
  } catch {
    case ex: BreakControl =>
      if (ex ne breakException) throw ex
  }
}

breakable 実装の結果として、 break関数によってスローされた例外は無視されますが、ループは停止します

def break(): Nothing = { throw breakException }

これは、このステートメントがどのように機能するかを理解するために重要です、特に複数のループの場合。

3. シンプルなループ

単純なforループを記述し、breakステートメントを使用してそれを終了しましょう。

breakable {
  for (i <- Range(0, 10)) yield {
    if (i > 3) {
      break()
    }
    println(s"$i * 2 = ${i * 2}")
  }
}

コンソール出力を取得します。

0 * 2 = 0
1 * 2 = 2
2 * 2 = 4
3 * 2 = 6

または、Breaksクラスのインスタンスを使用して上記を記述できます。

val loop = new Breaks
loop.breakable {
  for (i <- Range(0, 10)) yield {
    if (i > 3) {
      break()
    }
    println(i * 2)
  }
}

4. ネストされたループ

ここで、複数のループがあるより複雑なシナリオを考えてみましょう。

ここでは、両方のループに単一のbreakステートメントを使用します。

var i = 0
breakable {
  while (i < 4) {
    var j = 1
    while (j < 3) {
      if (i == 3) {
        break()
      }
      println(s"i: $i, j: $j")
      j += 1
    }
    i += 1
  }
}

このスニペットを実行すると、コンソールに次のように出力されます。

i: 0, j: 1
i: 0, j: 2
i: 1, j: 1
i: 1, j: 2
i: 2, j: 1
i: 2, j: 2

それでは、より洗練されたアプローチを取り、ループから個別に抜け出しましょう。

var i = 0
val outerLoop = new Breaks
outerLoop.breakable {
  while (i < 4) {
    if (i == 3) {
      outerLoop.break()
    }
    var j = 2
    val innerLoop = new Breaks
    innerLoop.breakable {
      while (j < 6) {
        if (j == 5) {
          innerLoop.break()
        }
        println(s"i: $i, j: $j")
        j += 1
      }
    }
    i += 1
  }
}

コンソール出力を確認してみましょう。

i: 0, j: 2
i: 0, j: 3
i: 0, j: 4
i: 1, j: 2
i: 1, j: 3
i: 1, j: 4
i: 2, j: 2
i: 2, j: 3
i: 2, j: 4

5. バリエーションを試す

さらに、 Breaks クラスは、tryBreakable関数を提供します。 名前が示すように、この関数を使用すると、break関数が呼び出された場合を処理できます。

tryBreakable[Unit] {
  for (i <- Range(0, 10)) yield {
    if (i > 3) {
      break()
    }
    println(s"$i * 2 = ${i * 2}")
  }
} catchBreak {
  println("break called!")
}

このコードを実行すると、コンソール出力が表示されます。

0 * 2 = 0
1 * 2 = 2
2 * 2 = 4
3 * 2 = 6
break called!

6. 結論

この記事では、ループを終了する方法として、breakステートメントとBreaksクラスのユーティリティ関数を紹介しました。 これはデータ構造を処理する機能的でない方法ですが、役立つ場合があります。 選択するループがわからない場合は、 Loops in FunctionalScalaの記事を確認してください。

いつものように、上記の例のコードはGitHubから入手できます。