コードの呼び出しと引数の引き渡し
このページでは、コード・ユニットを呼び出して、そのコードに引数を渡す方法について説明します。
ここに示すコマンドの概要は、"コードを呼び出すコマンド" を参照してください。
コード・ユニットの呼び出し
コード・ユニットを呼び出す構文は、呼び出すコードのタイプ、およびそのコードから返される値を取得するかどうかによって異なります。
ObjectScript 関数を呼び出すには、次の形式の式を記述し、結果となる値が必要な場所にその式を含めます。
$functionName(args)
以下に例を示します。
set myvariable=$length("this is a sample string")
プロシージャを呼び出すには、プロシージャ名を参照する構文を使用して、DO コマンドまたは他のいずれかのコードを呼び出すコマンドを使用します。
DO procedure^routinename
JOB procedure^routinename
このコマンドが同じルーチン内にある場合は、^routinename の部分を省略できます。
プロシージャが引数を受け入れる場合は、以下のように末尾に引数リストを含めることができます。
DO procedure^routinename(argument1,argument2)
プロシージャの実装によっては、値を返すことができます。値を返す場合、値を取得するには、以下の形式の式を記述します。
$$procedure^routinename
以下に例を示します。
set myvariable=$$procedure^routinename
このコマンドが同じルーチン内にある場合は、^routinename の部分を省略できます。
前述のとおり、プロシージャが引数を受け入れる場合は、以下のように末尾に引数リストを含めることができます。
$$procedure^routinename(argument1,argument2)
プライベート・プロシージャを定義するルーチンの外部からそのプライベート・プロシージャにアクセスしようとすると、<NOLINE> エラーが発生します。
クラス・メソッドを呼び出すには、以下の形式の式を使用します。
##class(Package.Class).MethodName(args)
以下に例を示します。
do ##class(Package.Class).MethodName(args)
または、
set myvariable=##class(Package.Class).MethodName(args)
プロシージャとは異なり、メソッドが引数を取らない場合でも、末尾の括弧を含める必要があります。
インスタンス・メソッドを呼び出すには、まず関連するオブジェクトへの参照を含む OREF が必要です。以下に例を示します。
set oref=##class(Sample.Class).%OpenId(10000)
do oref.WriteAddress()
または、
set oref=##class(Sample.Class).%OpenId(10000)
set myvariable=oref.WriteAddress()
詳細とバリエーションは、"登録オブジェクトを使用した作業" を参照してください。
仮引数リストと例
各 ObjectScript 関数、各プロシージャ (または、他の形式のサブルーチン)、および各メソッドには、引数のコンマ区切りリストである、仮引数リストがあります (または持つことができます)。このセクションでは、基本的な例を示します。
ObjectScript 関数の場合は、対応するリファレンス・ページに仮引数リストが示されます。例えば、$LENGTH 関数のリファレンス・ページには、仮引数リストが次のように示されます。
$LENGTH(expression,delimiter)
メソッドの場合は、クラス・ドキュメントに仮引数リストと生成されたコメントが示されます。IDE で直接コードを表示することもできます。ObjectScript 関数のドキュメントとは異なり、仮引数リストには引数の期待値と既定値に関する情報が含まれます。
例えば、%Library.FileOpens in a new tab には、NormalizeFilename() メソッドの仮引数リストが次のように示されます。
classmethod NormalizeFilename(filename As %String, directory As %String = "") as %String
引数の引き渡し (基本)
コード・ユニットを呼び出す場合、通常、以下の一般的な形式の構文を使用して引数を渡します。
codeunitidentifier(arg1,arg2,arg3)
以下の一般的な点に注意してください。
-
この構文は、引数を値で渡します。あまり一般的でない方法として、引数を参照で渡すこともできます。
-
一部のコード・ユニットは、引数を受け入れません。
コード・ユニットがメソッドまたは ObjectScript 関数である場合は、名前の後に括弧を含める必要があります。コード・ユニットがサブルーチンである場合は、それがどのような形式であっても、名前の後に括弧を含める必要はありません。
-
InterSystems IRIS は、指定された引数を、位置によって、仮引数リストの対応する引数にマップします。したがって、実リストの先頭にある引数の値は仮リストの先頭にある変数に配置され、2 番目の値は 2 番目の変数に配置され、以降の値も同様に配置されます。
これらの引数の照合は、名前ではなく、引数の位置で行われます。
-
一部の引数が省略可能な場合もあります。ある引数が省略可能で、その後ろの引数を指定する必要がある場合は、コンマを使用して、渡さない引数をスキップします。以下に例を示します。
set myval=##class(Sample.MyClass).MyMethod(arg1,,,arg4)
-
仮引数リストにあるよりも多くの引数を渡すと、<PARAMETER> エラーが発生します。(これには、可変個数の引数を受け入れるコード・ユニットは含まれません。これらでは、<PARAMETER> エラーは発生しません。)
バリエーションについては、以下のセクションで説明します。
参照渡しまたは出力引数
一部の引数リストには、1 つ以上の引数の前に、キーワード ByRef またはキーワード Output が含まれます。以下に例を示します。
-
%Library.PersistentOpens in a new tab には、%OpenID() メソッドの仮引数リストが次のように示されます (読みやすくするために改行を追加しています)。
classmethod %OpenID(id As %String="", concurrency As %Integer = -1, ByRef sc As %Status = $$$OK) as %ObjectHandle
-
%Library.FileOpens in a new tab には、Exists() メソッドの仮引数リストが次のように示されます。
classmethod Exists(filename As %String, Output return As %Integer) as %Boolean
このような場合、こうしたコード・ユニットを呼び出す際には、ByRef または Output 引数の直前にピリオドを配置します。つまり、引数はリテラルまたは他の種類の式ではなく、変数でなければなりません。
この場合、指定された引数は参照渡しされます。一般に、これは、この引数が呼び出しているコード・ユニットによって設定または更新されることを意味します。同様に、これは、引数にはユーザが処理方法の決定などに使用するための値が含まれることを意味します。
例えば、%Library.FileOpens in a new tab クラスの Exists() メソッドを呼び出す場合は、2 つ目の引数の前にピリオドを使用します。
set status=##class(%Library.File).Exists("c:\temp\check.txt",.returncode)
クラス・リファレンスに示されているように、2 つ目の引数には、この確認の実行時にオペレーティング・システムから取得した値が含まれます。
同様に、すべての永続クラスによって継承される %Library.PersistentOpens in a new tab の %OpenID() メソッドを呼び出す場合は、3 つ目の引数の前にピリオドを使用します。
set myvar=##class(MyPackage.MyClass).%OpenId(10034,,.statuscode)
クラス・リファレンスに示されているように、3 つ目の引数には、成功または失敗を示すステータス・コード (および失敗の場合は理由) が含まれます。
ObjectScript 関数を除き、すべてのコード・ユニットは、参照によって渡された引数を受け入れるように記述できます。
この方法でのメソッドの定義の詳細は、"引数の渡し方の指示" を参照してください。
比較 :値による引数と参照による引数
このセクションでは、引数を渡す 2 つの方法の違いについて説明します。まず、添え字なしでローカル変数を渡す方法について説明します (最も一般的なシナリオ)。
他のプログラミング言語の場合と同様に、InterSystems IRIS は、各ローカル変数の値を格納するメモリ位置を持っています。変数の名前は、メモリ位置のアドレスとして機能します。
添え字なしのローカル変数をメソッドに渡すときは、その変数を値によって渡します。つまり、システムによってその値のコピーが作成され、元の値が変更されることはありません。代わりに、メモリ・アドレスを渡すには、引数リストの変数の名前の直前にピリオドを配置します。
この例を示すため、Test.Parameters というクラス内の次のメソッドを見てみましょう。
ClassMethod Square(input As %Integer) As %Integer
{
set answer=input*input
set input=input + 10
return answer
}
変数を定義し、それをこのメソッドに値によって渡すとします。
TESTNAMESPACE>set myVariable = 5
TESTNAMESPACE>write ##class(Test.Parameters).Square(myVariable)
25
TESTNAMESPACE>write myVariable
5
反対に、変数を参照によって渡すとします。
TESTNAMESPACE>set myVariable = 5
TESTNAMESPACE>write ##class(Test.Parameters).Square(.myVariable)
25
TESTNAMESPACE>write myVariable
15
以下のメソッドを考えてみます。これは、受け取った引数の内容を書き込みます。
ClassMethod WriteContents(input As %String)
{
zwrite input
}
ここで、3 つのノードが含まれる配列があるとします。
TESTNAMESPACE>zwrite myArray
myArray="Hello"
myArray(1)="My"
myArray(2)="Friend"
この配列をメソッドに値によって渡すと、最上位のノードのみが渡されます。
TESTNAMESPACE>do ##class(Test.Parameters).WriteContents(myArray)
input="Hello"
この配列をメソッドに参照によって渡すと、配列全体が渡されます。
TESTNAMESPACE>do ##class(Test.Parameters).WriteContents(.myArray)
input="Hello"
input(1)="My"
input(2)="Friend"
グローバルの 1 つのノードの値をメソッドに渡すことができます。
TESTNAMESPACE>zwrite ^myGlobal
^myGlobal="Start"
^myGlobal(1)="Your"
^myGlobal(2)="Engines"
TESTNAMESPACE>do ##class(Test.Parameters).WriteContents(^myGlobal)
input="Start"
グローバルをメソッドに参照によって渡そうとすると、構文エラーが発生します。
TESTNAMESPACE>do ##class(Test.Parameters).WriteContents(.^myGlobal)
^
<SYNTAX>
以下の表は、そのすべてのバリエーションを示しています。
変数の種類 | 値渡し | 参照渡し |
---|---|---|
ローカル変数 (添え字なし) | これらの変数を渡す標準的な方法 | 可能 |
ローカル (添え字付き) (配列) | 1 つのノードの値を渡す | これらの変数を渡す標準的な方法 |
グローバル変数 (添え字付き、または添え字なし) | 1 つのノードの値を渡す | この方法では渡せません (グローバルのデータがメモリ内にありません) |
オブジェクト参照 (OREF) * | これらの変数を渡す標準的な方法 | 可能 |
* オブジェクトを表す変数がある場合、オブジェクト参照 (OREF) によってそのオブジェクトを参照します。OREF を引数として渡す場合、通常それを値で渡します。ただし、OREF はオブジェクトへのポインタであるため、事実上オブジェクトを参照渡ししていることになります。メソッド内のオブジェクトのプロパティの値を変更すると、オブジェクトのコピーではなく、実際のオブジェクトが変更されます。OREF の参照渡しは許可されており、異なるオブジェクトを指すよう OREF を変更する場合に使用できます。これは、一般的な使用法ではありません。オブジェクトとオブジェクト参照の詳細は、"オブジェクト" を参照してください。
可変個数の引数の引き渡し
一部のコード・ユニットは、可変個数の引数を受け入れることができます。以下に例を示します。
-
$CLASSMETHOD 関数のリファレンス・ページには、仮引数リストが次のように示されます。
$CLASSMETHOD(classname, methodname, arg1, arg2, arg3, ... )
この場合、arg1、arg2、arg3 はプレースホルダで、3 つの末尾のピリオドは、この関数が可変個数の引数を受け入れることができることを示します。
-
%SQL.StatementOpens in a new tab には、%Execute() メソッドの仮引数リストが次のように示されます。
method %Execute(%parm...) as %SQL.StatementResult
引数の後の 3 つのピリオドに注意してください。この構文は、メソッドが可変個数の引数を受け入れることを示しています。
このような可変個数の引数を使用すると、個数が変化する引数セットを、事前に知らされていない引数リストを持つ別のコード・ユニットに渡すことができます。可変個数の引数を受け入れるすべてのケースで、適用されるダウンストリームのコード・ユニットが期待する順序で、これらの引数をリストする必要があります。これらの引数は、通常どおりコンマで区切ります。(または、サブセクションの説明に従って、多次元配列を作成して渡します。)
例えば、$CLASSMETHOD 関数では、クラス・メソッドを呼び出し、これにそのメソッドの任意の引数を渡すことができます。MyPkg.MyClass に、以下のシグニチャを持つメソッドがあるとします。
ClassMethod SampleMethod(arg1 as %Integer,arg2 as %String,arg3 as %String) as %String {
}
このメソッドは、以下のように呼び出すことができます。
set a=10
set b="abc"
set c=$username
set myvar=$CLASSMETHOD("MyPkg.MyClass","SampleMethod",a,b,c)
同様に、上記のとおり、%Execute() メソッドは可変個数の引数を受け入れ、それらはすべて順番に、%SQL.StatementOpens in a new tab インスタンスによって実行されるクエリに渡されます。
この方法でのメソッドの定義の詳細は、"可変個数の引数の指定" を参照してください。
バリエーション :多次元配列の使用法
メソッドが可変個数の引数を受け入れる場合、引数を含む多次元配列を作成して渡すことができます。これは、前のサンプル・メソッドを例として使用すると、うまく説明できます。
set myargs(1)=10
set myargs(2)="abc"
set myargs(3)=$username
set myargs=3
set myvar=$CLASSMETHOD("MyPkg.MyClass","SampleMethod",myargs...)
多次元配列の最上位ノードは配列要素の数を示し、添え字は 1 で始まる整数です。また、多次元配列の名前の後の 3 つのピリオドにも注意してください。
この手法は、%SQL.StatementOpens in a new tab を使用する際に、可変個数の引数を渡す便利な方法を提供します。以下に例を示します。
Set sql="SELECT * FROM Test.Test WHERE A=?"
Set params($INCREMENT(params))="value 0"
If condition1 {
Set sql=sql_" AND B=?"
Set params($INCREMENT(params))="value 1"
}
If condition2 {
Set sql=sql_" AND C=?"
Set params($INCREMENT(params))="value 2"
}
Set statementResult=##class(%SQL.Statement).%ExecDirect(,sql,params...)