【Swift】ラベルを使って多重ループや多重スコープから一気に抜ける。(Swift 2.1、XCode 7.2)
ラベルとは
ラベルとは、制御文につける名前のことであり、ラベルを利用すれば多重ループや多重スコープの中から一気に抜けだしたり、処理をスキップできるようになる。
ラベルは以下のように定義する。
1 2 |
ラベル名:制御文 { } |
ループでラベルを利用する
例えば、以下のコードのような2重ループがあったとする。フラグの値がfalseだったら2重ループを抜けるもので、内側のループ内でフラグ判定が行われてbreakでループを抜けたら、外側のループでもフラグ判定を行いbreakでループを抜けるという2回の判定処理を書かなくてはならない。
ループを深くするコーディングの書き方自体が好ましく無いという考えもあるが、このように、ループごとにループ継続判定を行わなければならないのは冗長だ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
/* ** フラグの値がfalseなら2重ループを抜ける */ var loopFlag:Bool = false //ループフラグ //2重ループ for (var i = 1; i < 10 ; i++) { for (var k = 1; k < 5 ; k++) { print("ループ\(i)の\(k)") if( loopFlag == false ){ break } } if( loopFlag == false ){ break } } //実行結果 //ループ1の1 |
そこで利用されるのがラベルだ。以下のコードのように制御文(例ではfor)の先頭にラベルをつける。そして、ループを抜けたい箇所で「break ラベル名」と記述するとラベルをつけた制御文を一気に抜けることができる。コードがスッキリした。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
/* ** フラグの値がfalseならラベルを使ってループを抜ける */ var loopFlag:Bool = false testLabel:for (var i = 1; i < 10 ; i++) { for (var k = 1; k < 5 ; k++) { print("ループ\(i)の\(k)") if( loopFlag == false ){ break testLabel } } } //実行結果 //ループ1の1 |
ループを抜けるのではなく、指定したループの先頭に移動してループを継続したい場合はcontinueを使う。以下のコードはフラグがtrueの場合はループの先頭に移動して処理を再開する例。実行結果を見ると、ループ内のcontinue以降の処理が行われなかったことが分かる。
なお、continueで移動したときはループカウンタ(例ではiとk)はインクリメントされる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
/* ** フラグの値がfalseならラベルを使ってループの先頭に移動する */ var loopFlag = true var number = 10 test:for (var i = 1; i < 2 ; i++) { for (var k = 1; k < 3 ; k++) { if( loopFlag == true ){ continue test } number = 77 } } print(number) //実行結果 //10 |
条件分岐でラベルを利用する
ラベルはループ処理だけでなく、ifやswitchの条件分岐でも使える。以下のコードは2重のif文を「break ラベル」で抜ける例。breakを発行したあとのif文の中の処理が行われていないことが分かる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
/* ** フラグの値がfalseならラベルを使ってif文を抜ける */ var testFlag1:Bool = true var testFlag2:Bool = false var number = 0 testLabel:if(testFlag1 == true) { number = 10 if(testFlag2 == true) { number = 20 } else { break testLabel } number = 30 } print(number) //実行結果 //10 |
ちなみに、ループの無いところでラベルを指定しないbreakを使うことはできない。以下のコードはコンパイルエラーになる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
/* ** ラベルをつけないbreakはif文では使えない */ var testFlag1:Bool = true var testFlag2:Bool = false var number = 0 if(testFlag1 == true) { number = 10 if(testFlag2 == true) { number = 20 } else { break //エラー } number = 30 } //エラー //error: unlabeled 'break' is only allowed inside a loop or switch, a labeled break is required to exit an if or do |
処理ブロックでラベルを利用する
ループや条件判定のブロックの中ではなく、ひとかたまりの処理を一気に抜けたいときがある。そういうときは通常、ひとかたまりを関数にするのが常套手段だが、以下のコードのようにdoブロックを使って処理を抜けることができる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
/* ** ラベルを使って処理ブロックを抜ける */ var testFlag = true testLabel:do { print("1") print("2") if(testFlag == true) { break testLabel } print("3") print("4") } //実行結果 //1 //2 |
ちなみにif文やswitch文と同様に、doブロックの中でもラベルを指定しないbreakを使うことはできない。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/* ** doブロックでbreakのみは使えない。 */ do { print("1") print("2") break print("3") print("4") } //エラー //error: unlabeled 'break' is only allowed inside a loop or switch, a labeled break is required to exit an if or do |