Scala にも break はある
Scala2.8.0からは break が標準でサポートされています。
JavaやCと違い、Scalaの break は制御構文ではなくて、例外とブロックを使ったライブラリによる実装となっています。
使い方
Breaksをインポートする
import scala.util.control.Breaks
Breaksのインスタンスを作成する
これがbreakによる脱出の境界/スコープを定めることになります。
val b = new Breaks
インスタンスを明示したbreakの書き方
b.breakable {
for (x <- 1 to 100) {
println(x)
if (x == 50) b.break
}
}
もっと簡潔に書きたい
importを使って省略します。
import b.{breakable,break}
breakable {
....
break
}
脱出するbreakableは明示によって外側のものも選べる
val b1 = new Breaks
val b2 = new Breaks
b1.breakable {
for (x <- 1 to 100) {
b2.breakable {
for (y <- 1 to 100) {
println(y)
if (y == 10) b1.break
}
}
}
}
b2のなかから一気にb1を脱出しています。
仕組みと注意点
Breaksのソースはとても分かり易いので、Predef読解に挑んで <:< などで撃沈した人も安心して読めます。
breakは、実際のところ例外(固有のインスタンス)をスローしているだけで、breakableはその例外をキャッチして自分のインスタンスの所有する例外インスタンスかどうかを判断しているだけです。
なので、たとえば以下のコードは意図したように動作しません。
breakable {
try {
break
} catch {
case a: Throwable => println("caught!")
}
}
tryから一気にbreakableの外に出たいところですが、この例だと例外がキャッチされてしまい、そのあとの処理も続行してしまいます。
breakに用いられている例外は Throwableの子孫です(Exceptionの子孫ではありません)
continueはないの?
まあやっていることは同じですが、いらないんじゃないかと。
そもそもbreakは標準ライブラリでも用いられてはいるものの、これもいらないと思います。そんなに見た目きれいになりません。広域脱出のほうが見やすいってことも多いとは思いますので使いようかな?