do制御構文

繰り返し制御構文としてwhile制御構文を取り上げたが、これと似た制御構文にdoがある。PowerShell Coreのdo制御構文は次のようにdo-whileまたはdo-untilの形式で使用する。条件が満たされている場合は繰り返す、または、条件が満たされるまでは繰り返す、という動作を実現する。

do-while制御構文

do {
    処理
}
while (条件)

do-until制御構文

do {
    処理
}
until (条件)

while制御構文の場合、while制御構文の条件を満たした場合に、ブロック内の処理を実施する。do制御構文もwhile制御構文とよく似ているが、while制御構文はかならず最初に条件が評価されるのに対し、do制御構文ではブロックの中の処理を1回実行したあとでwhile()またはuntil()の式が評価されるという大きな違いがある。つまり、do制御構文ではブロックの中の処理はかならず1回は実行されるということである。

while制御構文とdo制御構文の使い分けは、ブロックの中を必ず1回は処理する必要があるかどうか、ということになる。ブロックの中を必ず実行したい場合にはdo制御構文が便利だし、そうではない場合にwhile制御構文が便利ということになる。しかし、どちらを使っても同じことは実行できるので、最終的には書き手の好みということにもなってくる。

while()またはuntil()で指定できる演算子などは次のようなものがある。このあたりはwhile制御構文で使用できるものがそのまま使用できる。

演算子 内容
-eq 等価
-ne 等価ではない
-gt よりも大きい 
-ge よりも大きいまたは等しい
-lt よりは少ない
-le よりは少ないまたは等しい
-like ワイルドカードパターンに一致する
-notlike ワイルドカードパターンに一致しない
-match 正規表現パターンに一致する
-notmatch 正規表現パターンに一致しない
-contains 参照値がコレクションに含まれている
-notcontains 参照値がコレクションに含まれていない
-in テスト値がコレクションに含まれている
-notin テスト値がコレクションに含まれていない
-is 同じオブジェクト型である
-isnot 同じオブジェクト型ではない

繰り返し説明しておくが、PowerShell Coreで使用できる比較演算子はシェル(具体的にはtestコマンド)で使用される比較演算子とよく似ている。JavaやC言語といったプログラミング言語では見慣れない形式なので最初は違和感を覚えるかもしれないが、こうした比較演算子を使うプログラミング言語はいくつかあるので慣れておくと便利だ。

while()とuntil()は式を評価した結果の受け取り方が逆になる。while()は「条件を満たしている場合は繰り返す」ということになり、until()は「条件を満たすまで繰り返す」ということになる。until()は「条件を満たしていない場合は繰り返す」とも言える。

どちらを使っても条件は指定できるので、各人の好みや考え方で選べばよい。どちらでもよいと思うが、そこのコードを読む人にとって意図が汲み取りやすくなる方を使うべきだろう。

do制御構文の実行サンプル

簡単なサンプルを通じてdo制御構文の動作を理解してみよう。まず、次の例だ。これはdo-whileの実行例で、変数iの値が10よりも小さい間はブロックの中の処理を繰り返し実行する。

do-whileの実行サンプル

PS /Users/daichi> $i=0
PS /Users/daichi> do {
>> $i
>> $i++
>> }
>> while ($i -lt 10)
0
1
2
3
4
5
6
7
8
9
PS /Users/daichi>

do-whileは比較的理解しやすいだろう。while制御構文のwhileの位置がブロックの後ろに移動したと考えればよく、繰り返しが終了する条件はwhile制御構文と同じだ。

次にdo-untilの使用例を示す。この例ではuntil()において変数iの値が10になるまで繰り返す、という指定を行っている。つまり、until()で指定している$i -eq 10という条件を満たすと繰り返し処理を終了する。untilという前置詞/接続詞が示すように、その条件を満たす「まで」ブロックの中の処理を繰り返すということになる。

do-untilの実行サンプル

PS /Users/daichi> $i=0
PS /Users/daichi> do {
>> $i
>> $i++
>> }
>> until ($i -eq 10)
0
1
2
3
4
5
6
7
8
9
PS /Users/daichi>

do-whileもdo-untilも、式の評価結果に対する動作が逆になっているだけで、それ以外は基本的に同じことをやっている。

do制御構文とbreak/continueの関係

繰り返し構文を使う場合、ループ処理を抜けたりするためのbreakやcontinueなどの機能がどのように働くのかを把握しておく必要がある。まずbreakについてだが、これは簡単だ。breakに到達した時点で、そのループを抜ける。

breakに到達すると繰り返し処理を抜ける

PS /Users/daichi> $i=0
PS /Users/daichi> do {
>> if ($i -eq 5) { break }
>> $i
>> $i++
>> }
>> while ($i -lt 10)
0
1
2
3
4
PS /Users/daichi>

気をつけないといけないのはcontinueだ。do制御構文のブロックの中でcontinueに到達すると、処理は次の判定処理に飛ぶ。つまりdo-whileならwhile()の式へ飛ぶし、do-untilならuntil()の式へ飛ぶ。次の例を見てみよう。

continueに到達すると式へ飛ぶ

PS /Users/daichi> $i=0
PS /Users/daichi> do {
>> if ($i -eq 5) { continue }
>> $i
>> $i++
>> }
>> while ($i -lt 10)
0
1
2
3
4
^C
PS /Users/daichi>

上記のサンプルでは、continueに到達した時点でwhile()の$i -lt 10に飛ぶ。この条件を満たしているので、再びブロックの最初に処理が飛ぶ。そこで再びcontinueが実行され、while()の$i -lt 10に飛ぶ。と、このように無限ループが発生している。サンプルではCtrl-Cを押して処理を終了させている。

continueはwhile制御構文の場合には次の繰り返し処理へ移動するといったような動作になるが、do制御構文の場合には次の式へ移動するといった動作になる。このあたりの動作を勘違いしていると上記サンプルのように無限ループになってりするので注意しておこう。

参考資料