WHILE (ObjectScript)
構文
WHILE expression,... {
code
}
引数
引数 | 説明 |
---|---|
expression | テスト条件。1 つ、または複数のコンマ区切りのテスト条件を指定することができます。それらはすべて、コード・ブロックの実行に対して True でなければなりません。 |
code | 中括弧で囲まれた ObjectScript コマンドのブロックです。 |
概要
WHILE は expression をテストし、expression が TRUE と評価された場合に、開き中括弧と閉じ中括弧の間のコード・ブロック (1 つ以上のコマンド) を実行します。WHILE は、expression が TRUE と評価されている限り、コードのブロックを繰り返し実行します。expression が True でない場合、中括弧内のコード・ブロックは実行されず、閉じ中括弧 ( } ) に続く次のコマンドが実行されます。
プログラマは WHILE の無限ループを回避するために、注意を払う必要があります。
開き中括弧や閉じ中括弧は、1 行で独立して記述するか、コマンドと同じ行に記述できます。開き中括弧や閉じ中括弧は、列 1 に記述してもかまいませんが、お勧めはできません。推奨されるプログラミング手法として、入れ子になったコード・ブロックの開始と終了を示すために、中括弧はインデントするようにしてください。開き中括弧の前後に空白を入れる必要はありません。閉じ中括弧の前に空白を入れる必要はありません。引数のないコマンドに続く中括弧の場合も同様です。中括弧の空白に関する唯一の要件は、閉じ中括弧とその後のコマンドを、スペース、タブ、または改行で区切る必要があるということです。
中括弧内のコードのブロックは、1 つ以上の ObjectScript コマンドと関数の呼び出しで構成される可能性があります。コード・ブロックは複数行にわたる場合があります。インデント、改行、空白スペースは、コード・ブロック内で許可されています。コード・ブロック内のコマンドとコマンド内の引数は、1 つ以上の空白スペース、または改行で分けられます。
引数
expression
ブーリアンのテスト条件。単一の式かコンマで区切られた式のリストの形式をとります。expression を TRUE (ゼロ以外の数値) として評価した場合、InterSystems IRIS は WHILE ループを実行します。通常、expression は x<10 や "apple"="apple" などの条件テストですが、ゼロ以外の数値に評価される値はすべて TRUE になります。例えば、7、00.1、“700”、“7dwarves” などは、すべて TRUE と評価されます。ゼロに評価される値はすべて FALSE になります。例えば、0、-0、および非数値文字列は、すべて FALSE と評価されます。
expression リストでは、InterSystems IRIS は左から右の順で、個別の式を評価します。0 (FALSE) に評価される式に遭遇すると、評価を終了します。FALSE に評価される式の右側にある式には、検証やテストが実施されません。
すべての式がゼロ以外の数値 (TRUE) に評価される場合、InterSystems IRIS は WHILE ループ・コード・ブロックを実行します。expression が TRUE に評価されている限り、InterSystems IRIS は各ループの先頭で expression をテストしながら、WHILE ループを繰り返し実行します。いずれかの式が FALSE に評価されると、InterSystems IRIS は、WHILE の閉じ中括弧の後の次のコード行を実行します。
例
以下の例では、WHILE ループを指定した回数実行します。ループを実行する前に、expression がテストされます。
Mainloop
SET x=1
WHILE x<10 {
WRITE !," Looping",x
SET x=x+1
}
WRITE !,"DONE"
QUIT
以下の 2 つの例では、2 つの expression テストを実行します。2 つのテストはコンマで区切られています。両方のテストが True に評価される場合、WHILE ループが実行されます。そのため、これらのプログラムは、リストのすべての項目、またはリスト内の指定のサンプル・サイズの項目を返します。
SET mylist=$LISTBUILD("a","b","c","d","e")
SET ptr=0,sampcnt=1,sampmax=4
WHILE 1=$LISTNEXT(mylist,ptr,value),sampcnt<sampmax {
WRITE value," is item ",sampcnt,!
SET sampcnt=sampcnt+1
}
IF sampcnt<sampmax {WRITE "This is the whole list"}
ELSE {WRITE "This is a ",sampcnt-1," item sample of the list"}
SET mylist=$LISTBUILD("a","b","c","d","e")
SET ptr=0,sampcnt=1,sampmax=10
WHILE 1=$LISTNEXT(mylist,ptr,value),sampcnt<sampmax {
WRITE value," is item ",sampcnt,!
SET sampcnt=sampcnt+1
}
IF sampcnt<sampmax {WRITE "This is the whole list"}
ELSE {WRITE "This is a ",sampcnt-1," item sample of the list"}
WHILE と DO WHILE
WHILE コマンドは、ループを実行する前に expression をテストします。DO WHILE コマンドはループを一度実行し、そして expression をテストします。
WHILE および FOR
FOR または WHILE のいずれかを使用して、同じ操作を実行できます。つまり、イベントによって実行がループを抜けるまでループすることができます。ただし、どちらのループ構造を使用するかにより、コード・モジュールに対してシングル・ステップ (BREAK "S+" または BREAK "L+") デバッグの実行に影響があります。
FOR ループでは、スタックに新しいレベルがプッシュされます。WHILE ループでは、スタック・レベルは変更されません。FOR ループをデバッグする場合、FOR ループ内からスタックをポップすると (BREAK "C" GOTO または QUIT 1 を使用)、FOR コマンド構文の終了直後から、このコマンドでのシングル・ステップ・デバッグを続行できます。WHILE ループをデバッグする場合は、BREAK "C" GOTO または QUIT 1 を使用して発行してもスタックはポップされません。したがって、WHILE コマンドの終了後にシングル・ステップ・デバッグは続行されません。残りのコードはブレークなしで実行されます。
詳細は、"BREAK" コマンドおよび "BREAK コマンドによるデバッグ" を参照してください。
WHILE および CONTINUE
WHILE コマンドのコード・ブロック内で CONTINUE コマンドに出会うと、実行が即座に WHILE コマンドに戻ります。次に WHILE コマンドは expression テスト条件を評価し、その評価を基にしてコード・ブロック・ループを再実行するかどうかを決定します。したがって、CONTINUE コマンドの実行にはコード・ブロックの終了中括弧に到達するのとまったく同じ効果があります。
WHILE、QUIT、RETURN
code ブロック内の QUIT コマンドは WHILE ループを終了させ、終わりの中括弧に続くコマンドに制御を渡します。以下はその例です。
Testloop
SET x=1
WHILE x < 10
{
WRITE !,"Looping",x
QUIT:x=5
SET x=x+1
}
WRITE !,"DONE"
このプログラムは、Looping1 から Looping5 までを書き込み、その後 DONE を書き込みます。
WHILE コード・ブロックは入れ子にできます。つまり、WHILE コード・ブロックに、別のフロー制御ループ (別の WHILE、あるいは FOR または WHILE コード・ブロック) を含むことができます。内側の入れ子となったループの QUIT では、内側のループが終了して、そのループの外側のループに実行が移ります。詳細は、以下の例を参照してください。
Nestedloops
SET x=1,y=1
WHILE x<6 {
WRITE "outer loop ",!
WHILE y<100 {
WRITE "inner loop "
WRITE " y=",y,!
QUIT:y=7
SET y=y+2
}
WRITE "back to outer loop x=",x,!!
SET x=x+1
}
WRITE "Done"
RETURN を使用すると、WHILE ループや入れ子のループ構造内を含む任意の場所からルーチンの実行を終了させることができます。RETURN は常に現在のルーチンを終了し、呼び出し元のルーチンに戻るか、呼び出し元のルーチンがない場合はプログラムを終了します。RETURN は、コード・ブロック内から発行されたかどうかに関係なく、常に同じ動作を行います。
WHILE と GOTO
コード・ブロック内の GOTO コマンドは、ループ外のラベルへ実行を移動しループを終了します。同じコード・ブロック内のラベルに実行を移動することもあります。この場合、ラベルは入れ子にされたコード・ブロックに存在します。
GOTO コマンドでは、別のコード・ブロック内のラベルに実行を移すことはできません。このような構造を実行することはできますが、移動先のコード・ブロックのテスト条件が無効になるため、“不正” と見なされます。
以下は、適切な GOTO の形式です。
mainloop ; GOTO to outside of the code block
WHILE 1=1 {
WRITE !,"In an infinite WHILE loop"
GOTO label1
WRITE !,"This should not display"
}
WRITE !,"This should not display"
label1
WRITE !,"Went to label1 and quit"
mainloop ; GOTO to elsewhere within the same code block
SET x=1
WHILE x<3 {
WRITE !,"In the WHILE loop"
GOTO label1
WRITE !,"This should not display"
label1
WRITE !,"Still in the WHILE loop after GOTO"
SET x=x+1
WRITE !,"x=",x
}
WRITE !,"WHILE loop done"
mainloop ; GOTO from an inner to an outer nested code block
SET x=1,y=1
WHILE x<6 {
WRITE !,"Outer loop",!
SET x=x+1
label1
WRITE "outer loop iteration ",x-1,!
WHILE y<4 {
WRITE !," Inner loop iteration ",y,!
SET y=y+1
WRITE " return to "
GOTO label1
WRITE " This should not display",!
}
WRITE "Inner loop completed",!
}
WRITE "All done"
mainloop ; GOTO from an outer to an inner nested code block
SET x=1,y=1
WHILE x<6 {
WRITE !,"Outer loop",!
SET x=x+1
WRITE "outer loop iteration ",x-1,!
WRITE "Jumping into the "
GOTO label1
WRITE "This should not display",!
WHILE y<4 {
WRITE !," Inner loop iteration ",y,!
SET y=y+1
label1
WRITE "inner loop ",!
}
WRITE "Inner loop completed",!
}
WRITE "All done"
以下の形式の GOTO は実行可能ですが、GOTO の移動先ブロックの条件テストが無効になる (無視される) ため、“不正” と見なされます。
mainloop ; GOTO into a code block
SET x=1
WRITE "Jumped into the "
GOTO label1
WHILE x>1,x<6 {
WRITE "Top of WHILE loop x=",x,!
label1
WRITE "Bottom of WHILE loop x=",x,!!
SET x=x+1
}
mainloop ; GOTO from a code block into an IF clause block
SET x=1
WHILE x<6 {
WRITE !,"WHILE loop interation=",x,!
SET x=x+1
GOTO label1
WRITE "This should never display",!
IF x#2 { WRITE "in the IF clause",!
label1
WRITE "GOTO entry into the IF clause",!
WRITE x," is an odd number",!
}
ELSE {WRITE "in the ELSE clause",!
WRITE x," is an even number",! }
WRITE "Bottom of WHILE loop",!
}
WRITE "All done"