パラメータ渡しなしの DO コマンド
パラメータ渡しなしの DO コマンドは、サブルーチンと一緒の場合にのみ使用されます。DO entryref にパラメータを渡さない (つまり、param オプションを指定しない) で使用すると、呼び出し元のルーチンとそれによって呼び出されたサブルーチンで、同じ変数環境が共有されるという事実を利用できます。サブルーチンにより変数の更新が行われた場合、これらはすべて自動的に DO コマンドの後のコードで使用可能となります。
パラメータを渡さずに DO を使用する場合は、呼び出し元のルーチンと呼び出されるサブルーチンが同じ変数を参照していることを確認する必要があります。
Note:
プロシージャによる変数の処理は、まったく異なります。"ObjectScript の使用法" の "プロシージャ" を参照してください。
以下の例では、Start (呼び出し元のルーチン) と Exponent (呼び出されるサブルーチン) が 3 つの変数 num、powr、および result へのアクセスを共有しています。Start では、num と powr がユーザ指定の値に設定されます。これらの値は、Exponent が DO コマンドによって呼び出されたときに、自動的に Exponent でも利用できます。Exponent は、num と powr を参照し、計算した値を result に代入します。Exponent が RETURN コマンドを実行する場合、制御は DO の後の WRITE コマンドに即座に戻ります。WRITE コマンドは、result を参照して計算された値を出力します。
Start ; Raise an integer to a specified power.
READ !,"Integer= ",num QUIT:num=""
READ !,"Power= ",powr QUIT:powr=""
DO Exponent()
WRITE !,"Result= ",result,!
RETURN
Exponent()
SET result=num
FOR i=1:1:powr-1 { SET result=result*num }
RETURN
以下の例で、DO は pat によって参照されるオブジェクトで、Admit() メソッドを呼び出します。このメソッドはパラメータを受け取らず、また値も返しません。
DO pat.Admit()
以下の例では、DO が、現在のルーチン内の Init サブルーチンと Read1 サブルーチン、および Test ルーチン内の Convert サブルーチンを連続して呼び出します。
DO Init,Read1,Convert^Test
以下の例では、DO は拡張参照を使用して、別のネームスペース (SAMPLES ネームスペース) の fibonacci ルーチンを呼び出しています。
NEW $NAMESPACE
SET $NAMESPACE="USER"
DO ^|"SAMPLES"|fibonacci
パラメータ渡しの DO
パラメータ渡しが使用される場合、DO entryref は、呼び出したサブルーチン、プロシージャ、ユーザ指定関数、またはオブジェクト・メソッドに 1 つ、または複数の値を明示的に渡します。渡す値は、コンマで区切られたリストとして param オプションで指定されたものです。パラメータ渡しを行う場合は、呼び出されるサブルーチンがパラメータ・リスト付きで定義されているかを確認する必要があります。サブルーチンの定義の形式は、以下のとおりです。
>label( param)
label では、サブルーチン、プロシージャ、ユーザ指定関数、またはオブジェクト・メソッドのラベル名を指定します。param では、コンマで区切られた添え字なしのローカル変数名 1 つ、または複数からなるリストを指定します。以下はその例です。
Main
SET x=1,y=2,z=3
WRITE !,"In Main ",x,y,z
DO Sub1(x,y,z)
WRITE !,"Back in Main ",x,y,z
QUIT
Sub1(a,b,c)
WRITE !,"In Sub1 ",a,b,c
QUIT
DO コマンドで渡されるパラメータ・リストは、実パラメータ・リスト (実リスト) と呼ばれます。コード化されたルーチン・ラベルの一部として定義されるパラメータ変数のリストは、仮パラメータ・リスト (仮リスト) と呼ばれます。DO コマンドがルーチンを呼び出すとき、実リストのパラメータは、その位置に従って、仮リスト内の対応する変数にマップされます。上述の例では、1 番目の実パラメータ (x) の値は、サブルーチンの仮パラメータ・リストにある 1 番目の変数 (a) に代入され、2 番目の実パラメータ (y) の値は 2 番目の変数 (b) に代入されます。その後、サブルーチンは、仮パラメータ・リストの変数を参照することによって、渡された値にアクセスできます。
実パラメータ・リスト内の変数が、仮パラメータ・リスト内のパラメータよりも多い場合、InterSystems IRIS は <PARAMETER> エラーを発行します。
仮リスト内の変数が、実リスト内のパラメータよりも多い場合は、余った変数は未定義のままになります。以下の例は、仮パラメータ c が未定義のままになっています。
Main
SET x=1,y=2,z=3
WRITE !,"In Main ",x,y,z
DO Sub1(x,y)
WRITE !,"Back in Main ",x,y,z
QUIT
Sub1(a,b,c)
WRITE !,"In Sub1 "
IF $DATA(a) {WRITE !,"a=",a}
ELSE {WRITE !,"a is undefined"}
IF $DATA(b) {WRITE !,"b=",b}
ELSE {WRITE !,"b is undefined"}
IF $DATA(c) {WRITE !,"c=",c}
ELSE {WRITE !,"c is undefined"}
QUIT
実パラメータ値が指定されていない場合、仮パラメータに対し既定値を指定できます。
DO コマンドの実パラメータ・リストから、対応するパラメータを削除して、変数を未定義のままにできます。ただし、実パラメータを削除した個所に、プレースホルダとしてコンマを入れる必要があります。以下の例は、仮パラメータ b が未定義のままになっています。
Main
SET x=1,y=2,z=3
WRITE !,"In Main ",x,y,z
DO Sub1(x,,z)
WRITE !,"Back in Main ",x,y,z
QUIT
Sub1(a,b,c)
WRITE !,"In Sub1 "
IF $DATA(a) {WRITE !,"a=",a}
ELSE {WRITE !,"a is undefined"}
IF $DATA(b) {WRITE !,"b=",b}
ELSE {WRITE !,"b is undefined"}
IF $DATA(c) {WRITE !,"c=",c}
ELSE {WRITE !,"c is undefined"}
QUIT
... 構文を使用して、可変個数のパラメータを指定できます。
Main
SET x=3,x(1)=10,x(2)=20,x(3)=30
DO Sub1(x...)
QUIT
Sub1(a,b,c)
WRITE a," ",b," ",c
QUIT
DO コマンドは、パラメータの値渡し (DO Sub1(x,y,z) など)、または参照渡し (DO Sub1(.x,.y,.z) など) のいずれかを行います。同じ DO コマンド内で、値渡しと参照渡しを混合して指定することもできます。詳細は、"ObjectScript の使用法" の "パラメータ渡し" を参照してください。
以下の例は、値渡しと参照渡しの違いを示しています。
Main /* Passing by Value */
SET x=1,y=2,z=3
WRITE !,"In Main ",x,y,z
DO Sub1(x,y,z)
WRITE !,"Back in Main ",x,y,z
QUIT
Sub1(a,b,c)
SET a=a+1,b=b+1,c=c+1
WRITE !,"In Sub1 ",a,b,c
QUIT
Main /* Passing by Reference */
SET x=1,y=2,z=3
WRITE !,"In Main ",x,y,z
DO Sub1(.x,.y,.z)
WRITE !,"Back in Main ",x,y,z
QUIT
Sub1(&a,&b,&c) /* The & prefix is an optional by-reference marker */
SET a=a+1,b=b+1,c=c+1
WRITE !,"In Sub1 ",a,b,c
QUIT
間接指定の DO
間接指定を使用して、DO にターゲットのサブルーチンの場所を提供することができます。例えば、さまざまなメニュー関数を別のルーチン内の異なる場所に組み込む方法で、一般的なメニュー・プログラムを実装するとします。メイン・プログラム・コードで、名前による間接指定を使用して、DO コマンドにメニューの各選択項目に対応するサブルーチンの場所を提供することができます。
InterSystems IRIS オブジェクト・ドット構文を使用して、間接指定をすることはできません。ドット構文が実行時ではなく、コンパイル時に構文解析されるためです。
名前による間接指定の場合、間接指定演算子 (@) の右側の式の値が名前 (行ラベル またはルーチン) でなければなりません。以下のコード部分では、名前による間接指定によって、DO コマンドに Menu ルーチン内のターゲット・サブルーチンの場所が提供されています。
READ !,"Enter the number for your choice: ",num QUIT:num=""
DO @("Item"_num)^Menu
DO コマンドは、Menu 内のサブルーチンを呼び出します。このサブルーチンのラベルは、Item とユーザ指定の num 値が連結されたもの (Item1、Item2 など) です。
間接指定の引数形式を使用して、完全な DO 引数の代わりに、式の値を使用することもできます。例えば、以下の DO コマンドを見てみましょう。
DO @(eref_":fstr>0")
このコマンドは、fstr の値が 0 より大きい場合に、eref の値で指定されたサブルーチンを呼び出します。
詳細は、"ObjectScript の使用法" の "間接演算" を参照してください
引数後置条件付きの DO
DO コマンドのターゲット・サブルーチンを選択するには、引数後置条件式を使用できます。後置条件式が False (0) で評価される場合、InterSystems IRIS は関連付けられているサブルーチン呼び出しを無視します。後置条件式が True (1) で評価される場合、InterSystems IRIS は関連付けられているサブルーチン呼び出しを実行してから、DO コマンドに戻ります。DO コマンドの引数とその引数の両方で、後置条件を使用できます。
例えば、以下のコマンドを考えてみます。
DO:F>0 A:F=1,B:F=2,C
DO コマンドには後置条件式があり、F が 0 以下の場合、DO は実行されません。DO コマンドの引数にも、後置条件式があります。DO は後置条件のこれらの引数を使用して、実行するサブルーチン (A、B、C) を選択します。True 条件を満たすすべてのサブルーチンが、指定されている順番に実行されます。つまり、この例では、後置条件式のない C は常に実行されます。F が 1 の場合は A と C が実行され、F が 2 の場合は B とC が実行され、F が 3 (または他の任意の数) の場合は C が実行されます。True の既定として C を指定する場合は、次のようにします。
DO:F>0 A:F=1,B:F=2,C:((F'=1)&&(F'=2))
この例では、実行されるサブルーチンは 1 つのみになります。
以下の例で、DO コマンドは後置条件式を取り、その引数もそれぞれ後置条件式を取ります。この場合、最初の引数は後置条件式が 0 であるため、実行されません。2 つ目の引数は後置条件式が 1 であるため実行されます。
Main
SET x=1,y=2,z=3
WRITE !,"In Main ",x,y,z
DO:1 Sub1(x,y,z):0,Sub2(x,y,z):1
WRITE !,"Back in Main ",x,y,z
QUIT
Sub1(a,b,c)
WRITE !,"In Sub1 ",a,b,c
QUIT
Sub2(d,e,f)
WRITE !,"In Sub2 ",d,e,f
QUIT
DO によって呼び出されるオブジェクト (oref) メソッドのほとんどは、引数後置条件式を取ることができます。ただし、$SYSTEM オブジェクト・メソッドは、引数後置条件式を取ることができません。これを実行しようとすると、<SYNTAX> エラーが生成されます。
InterSystems IRIS では、式は必ず左から右の順番で評価されるため、引数後置条件式が評価される前に、式を含む引数が評価されます (エラーが生成される場合もあります)。
引数の後置条件を使用するときは、副作用がないことを確認してください。例えば、以下のコマンドを考えてみます。
DO @^Control(i):z=1
この場合 ^Control(i) には、後置条件 z=1 が True の場合に呼び出すサブルーチンの名前が含まれています。z=1 であるかどうかにかかわらず、InterSystems IRIS は ^Control(i) の値を評価し、それに従って、現在のグローバル・ネイキッド・インジケータを再設定します。z=1 が False の場合、InterSystems IRIS は DO を実行しません。ただし、グローバル・ネイキッド・インジケータは、DO を実行したかのようにリセットされます。ネイキッド・インジケータに関する詳細は、"グローバルの使用法" の "ネイキッド・グローバル参照" を参照してください。
後置条件式の評価方法に関する詳細は、"ObjectScript の使用法" の "コマンド後置条件式" を参照してください。