Skip to main content

This is documentation for Caché & Ensemble. See the InterSystems IRIS version of this content.Opens in a new tab

For information on migrating to InterSystems IRISOpens in a new tab, see Why Migrate to InterSystems IRIS?

演算子と式

Caché は、多様な演算子をサポートします。例えば、数学的な動作、論理比較などさまざまな動作を実行します。演算子は、最終的に 1 つの値に評価される変数や他のエンティティである式に対して作用します。この章では、式とさまざまな ObjectScript 演算子について説明します。以下の項目が含まれます。

演算子と式の概要

演算子とはシンボル文字で、対応するオペランドで実行する処理を指定するものです。各オペランドは、1 つ以上のまたは式アトムから構成されます。演算子とその演算子に対応するオペランドを一緒に使用する場合、以下の形式になります。

[operand] 演算子 operand

演算子の中には、1 つのオペランドのみを使用する単項演算子があります。2 つのオペランドを使用するものは、2 項演算子といいます。

式は、演算子とそこで使用されるオペランドで構成されます。このような式は、オペランドに対する演算子の演算結果を生成します。式は、含まれる演算子タイプに基づいて分類されます。

  • 算術式は算術演算子を含み、オペランドを数値として解釈し、数値結果を算出します。

  • 文字列式は文字列演算子を含み、オペランドを文字列として解釈し、文字列の結果を返します。

  • 論理式は関係演算子と論理演算子を含み、オペランドを論理解釈し、True (1) あるいは False (0) のブーリアン値を返します。

演算子記号の表

ObjectScript には、以下の演算子があります。

ObjectScript 演算子
演算子 実行される演算
. オブジェクトのプロパティあるいはメソッドへのアクセス
() 配列インデックスあるいは関数の引数呼び出し
+ 加算 (2項)、正値 (単項)
減算 (2項)、負値 (単項)
* 乗算
/ 除算
\ 整数除算
** べき乗
# 剰余
_ 連結
' 論理補数 (NOT)
= 等価テスト、代入
'= 非等価テスト
> より大きい

'>

<=

より大きくない (より小さい、あるいは等しい)
< より小さい

'<

>=

より小さくない (より大きい、あるいは等しい)
[ 包含
] 追従
]] 前後関係

&

&&

論理 AND (&& は AND の“簡易版”)

!

||

論理 OR (|| は OR の“簡易版”)
@ 間接演算
? パターン・マッチ

詳細は、以下のセクションで説明しています。

演算子の優先順位

ObjectScript で演算子の評価順序は、必ず左から右です。したがって、式の演算は表示された順番で実行されます。これは、特定の演算子の優先順位が他の演算子よりも高くなることがある他の言語と異なります。式で明示的に小括弧を使用して、特定の演算子を先に処理させることができます。

 WRITE "1 + 2 * 3 = ", 1 + 2 * 3,!  // returns 9
 WRITE "2 * 3 + 1 = ", 2 * 3 + 1,!  // returns 7
 WRITE "1 + (2 * 3) = ", 1 + (2 * 3),!  // returns 7
 WRITE "2 * (3 + 1) = ", 2 * (3 + 1),!  // returns 8

単項マイナス演算子

ObjectScript は、二項算術演算子より単項マイナス演算子を優先します。ObjectScript はまず数値式を検査し、単項マイナス演算子を実行します。その後、式を評価して結果を算出します。

  WRITE -123 - 3,!       // returns -126
  WRITE -123 + -3,!      // returns -126
  WRITE -(123 - 3),!     // returns -120

括弧と優先順位

式の評価の順序は、それぞれの式を対の小括弧で入れ子にして変更できます。小括弧は、囲んだ式 (算術式と関係式の両方) をグループ化し、ObjectScript が式で実行する演算の順序を制御します。以下の例を考えてみます。

  SET TorF = ((4 + 7) > (6 + 6)) // False (0)
  WRITE TorF

上記では、小括弧で 4 と 7、および 6 と 6 を加算しているため、論理式は 11 > 12 となり、結果は False になります。以下のコードと比較します。

  SET Value = (4 + 7 > 6 + 6) // 7
  WRITE Value

この場合、演算の優先順位は左から右になります。したがって、最初に 4 と 7 を加算します。その合計の 11 と 6 を比較し、11 は 6 より大きくなるため、論理演算の結果は 1 (True) になります。その後、1 に 6 を加算するため、結果は 7 になります。

優先順位により結果のタイプが異なることに注意してください。上記の例で、最初の式の演算は最終的にブーリアン値を返し、2 番目の式は数値を返します。

以下の例では、複数レベルの入れ子を示します。

 WRITE 1+2*3-4*5,!  // returns 25
 WRITE 1+(2*3)-4*5,!  // returns 15
 WRITE 1+(2*(3-4))*5,!  // returns -5
 WRITE 1+(((2*3)-4)*5),!  // returns 11

内側の入れ子の式から 1 レベルずつ外側に進み、各レベルで左から右へと式が評価されます。

Tip:

極めて単純な ObjectScript 式を除いて、すべての式全体を括弧で囲むことをお勧めします。これにより、評価の順序のあいまいさが解消され、コードの本来の意図について今後疑問が出ることもなくなります。

例えば、すべての演算子と同様に “&&” 演算子は、左から右の順に実行されるため、以下のコード例の最後の文は 0 に評価されます。

 SET x = 3
 SET y = 2
 IF x && y = 2 {
   WRITE "True",! } 
 ELSE {
   WRITE "False",! }

これは評価が次のように実行されるからです。

  1. 最初に、x が定義されていて、0 以外の値であるかどうかが確認されます。x は 3 なので評価は続行されます。

  2. 次に、y が定義されていて、0 以外の値であるかどうかが確認されます。y は 2 なので評価は続行されます。

  3. 次に、3 && 2 の値が評価されます。3 も 2 も 0 ではないので、この式は True で、1 に評価されます。

  4. 次に、返された値を 2 と比較します。1 は 2 ではないので、この評価は 0 を返します。

多くのプログラミング言語に精通している人にとって、これは予想外の結果です。x に0 でない値が定義されていて、y が 2 のときに True を返すことを意図している場合は、次のように括弧が必要です。

 SET x = 3
 SET y = 2
 IF x && (y = 2) {
   WRITE "True",! } 
 ELSE {
   WRITE "False",! }

関数と優先順位

関数など、式のタイプによって副次的作用が発生する場合があります。以下の論理式を考えてみます。

 IF var1 = ($$ONE + (var2 * 5)) {
    DO ^Test 
 }

ObjectScript は、最初に var1、次に関数 $$ONE、その次に var2 を評価します。その後、var2 を 5 倍し、最後に ObjectScript は、加算の結果が var1 の値に等しいかどうかをテストします。等しい場合、DO コマンドを実行して Test ルーチンを呼び出します。

別の例として、以下の論理式を考えてみます。

  SET var8=25,var7=23
  IF var8 = 25 * (var7 < 24) {
    WRITE !,"True" }
  ELSE {
    WRITE !,"False" }

Caché は、厳密に左から右の順に式を評価します。プログラマは、括弧を使用して優先順位を確立する必要があります。この場合、Caché はまず var8=25 を評価し、結果が 1 になります。次に、この 1 に括弧内の式の結果を乗算します。var7 は、24 より小さいので、括弧内の式は、1 と評価されます。したがって、Caché は、1 * 1 を乗算し、結果は 1 (True) となります。

ObjectScript 式は、値を算出するために評価される 1 つ以上の “トークン” です。最も単純な式は、リテラルあるいは変数です。

 SET expr = 22
 SET expr = "hello"
 SET expr = x

配列、演算子、多くの ObjectScript 関数の 1 つを使用して、さらに複雑な式を記述できます。

 SET expr = +x
 SET expr = x + 22
 SET expr = array(1)
 SET expr = ^data("x",1)
 SET expr = $Length(x)

式は、オブジェクト・プロパティ、インスタンス・メソッド呼び出し、クラス・メソッド呼び出しから構成されます。

 SET expr = person.Name
 SET expr = obj.Add(1,2)
 SET expr = ##class(MyApp.MyClass).Method()

ルーチン呼び出しの前に $$ を置き、ObjectScript ルーチン呼び出しを式で直接実行できます。

 SET expr = $$MyFunc^MyRoutine(1)

式は、返す値の種類で分類できます。

  • 算術式は算術演算子を含み、オペランドを数値として解釈し、数値結果を算出します。

     SET expr = 1 + 2
     SET expr = +x
     SET expr = a + b
    

    算術式で使用される文字列は、数値として評価されます (有効な数値がない場合は 0 となります)。また、単項加算演算子 (+) を使用すると、文字列値を数値に暗黙に変換します。

  • 文字列式は文字列演算子を含み、オペランドを文字列として解釈し、文字列の結果を返します。

     SET expr = "hello"
     SET expr = "hello" _ x
    
  • 論理式は関係演算子と論理演算子を含み、オペランドを論理解釈し、True (1) あるいは False (0) のブーリアン値を返します。

     SET expr = 1 && 0
     SET expr = a && b
     SET expr = a > b
    
  • オブジェクト式 は、結果としてオブジェクト参照を生成します。

     SET expr = object
     SET expr = employee.Company
     SET expr = ##class(Person).%New()

論理式

論理式は、論理演算子数値関係演算子文字列関係演算子 を使用します。式を評価し、1 (True) または 0 (False) のブーリアン値を返します。論理式は、通常、以下を使用します。

ブーリアン・テストでは、ゼロ以外の数値に評価される式はいずれもブーリアン 1 (True) の値を返します。ゼロの数値に評価される式はいずれもブーリアン 0 (False) の値を返します。Caché では、非数値文字列がゼロの数値を有しているものとして評価します。詳細は、"文字列から数値への変換" を参照してください。

論理演算子を使用することにより、複数のブーリアン論理式を組み合わせることができます。すべての Caché の式と同様に、これらは厳密に左から順に評価されます。論理演算子のタイプには、正規論理演算子 (& および !) と簡易論理演算子 (&& および ||) の 2 つがあります。

正規論理演算子を使用して論理式を組み合わせる場合、Caché では、すべての式の評価が完了する前にブーリアン値の結果が分かっていたとしても、指定された式をすべて評価します。これにより、すべての式の妥当性が保証されます。

簡易論理演算子を使用して論理式を組み合わせる場合、Caché ではブーリアン値結果の割り出しに必要な式のみを評価します。例えば、複数の AND テストをする場合、0 を返す最初の式によって全体のブーリアン値結果が決まります。この式の右側にある論理式は評価されません。これにより、不必要な時間的浪費となる式の評価を回避できます。

コンマ区切りリストを引数値として指定できるコマンドもあります。この場合、Caché ではリストの各引数を独立したコマンド文のように扱います。したがって、IF x=7,y=4,z=2IF x=7 THEN IF y=4 THEN IF z=2 と解析され、簡易論理演算子の文の IF (x=7)&&(y=4)&&(z=2) と機能的に同一となります。

以下の例では、IF テストにて正規論理演算子 (&) を使用しています。したがって、最初の関数が 0 (False) を返すため、自動的に式全体の結果が False になりますが、すべての関数が実行されます。

LogExp
 IF $$One() & $$Two() {
    WRITE !,"Expression is TRUE."  } 
 ELSE {
    WRITE !,"Expression is FALSE." }
One() 
 WRITE !,"one"
 QUIT 0
Two()
 WRITE !,"two"
 QUIT 1

以下の例では、IF テストにて簡易論理演算子 (&&) を使用しています。したがって、最初の関数の実行により 0 (False) を返すため、自動的に式全体の結果が False になります。2 番目の関数は実行されません。

LogExp
 IF $$One() && $$Two() {
    WRITE !,"Expression is TRUE."  } 
 ELSE {
    WRITE !,"Expression is FALSE." }
One() 
 WRITE !,"one"
 QUIT 0
Two()
 WRITE !,"two"
 QUIT 1

以下の例では、IF テストにてコンマ区切り引数を指定しています。コンマは論理演算子ではありませんが、簡易 && 論理演算子の指定と同じ効果があります。最初の関数の実行により 0 (False) を返すため、自動的に式全体の結果が False になります。2 番目の関数は実行されません。

LogExp
 IF $$One(),$$Two() {
    WRITE !,"Expression is TRUE."  } 
 ELSE {
    WRITE !,"Expression is FALSE." }
One() 
 WRITE !,"one"
 QUIT 0
Two()
 WRITE !,"two"
 QUIT 1

代入

ObjectScript の SET コマンドは、代入演算子 ( = ) を併用して変数に値を代入します。代入コマンドの右側に式が置かれます。

 SET value = 0
 SET value = a + b

ObjectScript では、代入コマンドの左側にも特定の関数を使用できます。

 SET pies = "apple,banana,cherry"
 WRITE "Before: ",pies,!

 // set the 3rd comma-delimited piece of pies to coconut
 SET $Piece(pies,",",3) = "coconut"
 WRITE "After: ",pies

文字列から数値への変換

文字列は数値、部分的数値、または非数値となり得ます。

  • 数値文字列はすべて数字で構成されます。例えば、"123""+123"".123""++0007""-0" となります。

  • 部分的数値の文字列とは、数字で始まり、非数値の文字が続く文字列です。例えば、"3 blind mice""-12 degrees" となります。

  • 非数値の文字列は数値ではない文字で始まります。例えば、" 123""the 3 blind mice""three blind mice" となります。

数値文字列

数値文字列または部分的文字列を算術式で使用する場合、文字列は数値として解釈されます。文字列で左から右に数値文字をスキャンしてこの数値を取得し、数値リテラルと解釈できる開始文字の最長シーケンスを見つけます。以下の文字が可能です。

  • 0 から 9 までの数字。

  • PlusSign プロパティ値および MinusSign プロパティ値。既定では、それらは “+” および “-” の文字となりますが、ロケールに依存します。%SYS.NLS.Format.GetFormatItem()Opens in a new tab メソッドを使用して、現在の設定を返します。

  • DecimalSeparator プロパティ値。既定では、これは “.” の文字となりますが、ロケールに依存します。%SYS.NLS.Format.GetFormatItem()Opens in a new tab メソッドを使用して、現在の設定を返します。

  • 文字の “e” および “E” は、シーケンス内で 4E3 などの科学的記数法を表す場合に、数値文字列の一部含むことができます。

NumericGroupSeparator プロパティ値 (既定では、“,” の文字) は、数値文字とはみなされないことに注意してください。したがって、文字列 "123,456" は部分的数値文字列となり、数 "123" に分解されます。

数値文字列および部分的数値文字列は、算術演算 (加算および減算) および「より大きい/より小さい」などの比較演算 (<、>、<=、>=) に優先して、キャノニック形式に変換されます。数値文字列は等値比較 (=、'=) に優先して、キャノニック形式へ変換されません。この理由は、それらの演算子が文字列比較にも使用されるためです。

以下の例は、数値文字列の算術比較を示しています。

  WRITE "3" + 4,!             // returns 7
  WRITE "003.0" + 4,!         // returns 7
  WRITE "++--3" + 4,!         // returns 7
  WRITE "3 blind mice" + 4,!  // returns 7

以下の例は、数値文字列の < (より小さい) 比較を示しています。

  WRITE "3" < 4,!             // returns 1
  WRITE "003.0" < 4,!         // returns 1
  WRITE "++--3" < 4,!         // returns 1
  WRITE "3 blind mice" < 4,!  // returns 1

以下の例は、数値文字列の <= 比較を示しています。

  WRITE "4" <= 4,!             // returns 1
  WRITE "004.0" <= 4,!         // returns 1
  WRITE "++--4" <= 4,!         // returns 1
  WRITE "4 horsemen" <= 4,!    // returns 1

以下の例は、数値文字列の等値比較を示しています。非キャノニック形式の数値文字列は、数値ではなく、文字列として比較されます。-0 は非キャノニック形式の数値文字列です。したがって、数値ではなく、文字列として比較されます。

  WRITE "4" = 4.00,!          // returns 1
  WRITE "004.0" = 4,!         // returns 0
  WRITE "++--4" = 4,!         // returns 0
  WRITE "4 horsemen" = 4,!    // returns 0
  WRITE "-4" = -4,!           // returns 1
  WRITE "0" = 0,!             // returns 1
  WRITE "-0" = 0,!            // returns 0
  WRITE "-0" = -0,!           // returns 0

非数値文字列

文字列の先頭の文字が数値文字ではない場合、すべての算術演算に対する文字列の数値は 0 となります。<、>、'>、<=、'<、および >= による比較演算でも、数値ではない文字列は 0 として扱われます。等号は数値的等値演算子および文字列比較演算子の両方として使用されるので、= および '= の演算では文字列比較が優先されます。PlusSign プロパティ値 (既定では +) を追加することで、文字列の数値的評価を強制することができます。x および y が異なる非数値文字列 (x=”Fred”、y=”Wilma” など) である場合、結果は以下の論理値となります。

x=y は False x=x は True +x=y は False +x=+y は True +x=+x は True
x'=y は True x=y は False +x'=y は True +x'=+y は False +x'=+x は False
x<y は FALSE x<x は FALSE +x<y は FALSE +x<+y は FALSE +x<+x は FALSE
x<=y は TRUE x<=x は TRUE +x<=y は TRUE +x<=+y は TRUE +x<=+x は TRUE

算術演算子

算術演算子は、オペランドを数値として解釈し、数値結果を生成します。文字列について演算する場合、算術演算子は、“文字列から数値への変換” のセクションで説明したルールに従って、文字列をその数値として扱います。

10 進数および $DOUBLE 浮動小数点数

Caché は、2 つの浮動小数点表現をサポートしています。ObjectScript の 10 進数の浮動小数点および IEEE 倍精度バイナリ浮動小数点です。

  • Caché は、既定で数値定数を ObjectScript の 10 進数の浮動小数点値として表します。これは $DECIMAL 数と呼ばれます。$DECIMAL 数は、2.2 のような小数値を正確に表すことができます。$DECIMAL() 関数は、IEEE 倍精度バイナリ浮動小数点数を対応する ObjectScript の 10 進数の浮動小数点数に明示的に変換するのに使用します。

  • Caché は、IEEE 倍精度バイナリ浮動小数点値もサポートしています。$DOUBLE() 関数は、数値定数を対応する IEEE 倍精度バイナリ浮動小数点値 ($DOUBLE 数と呼ばれます) に明示的に変換するのに使用します。$DOUBLE 数は、2.2 のような小数値を概算でのみ表すことができます。$DOUBLE 表現は、ほとんどのコンピュータがバイナリ浮動小数点演算のための高速ハードウェアを搭載しているため、通常、高速な科学計算を実行する場合に優先的に使用されます。

ObjectScript は、以下の状況で数値を対応する $DOUBLE 値に自動的に変換します。

  • 算術演算に $DOUBLE 値が含まれる場合、ObjectScript は演算のすべての数値を $DOUBLE に変換します。例えば、2.2 + $DOUBLE(.1)$DOUBLE(2.2) + $DOUBLE(.1) と同じです。

  • 演算の結果、大きすぎて ObjectScript の10 進数の浮動小数点で表すことができない数値 (9.223372036854775807E145 を超える数値) が生成された場合、ObjectScript は、<MAXNUMBER> エラーを発行するのではなく、この数値を自動的に $DOUBLE に変換します。

単項プラス演算子 (+)

単項プラス演算子 (+) は、単一のオペランドを数値として解釈します。オペランドが文字列値を持つ場合、それを数値に変換します。無効な文字に遭遇するまで、文字列の文字を数値として順番に解析することで、これを実行します。そして、適格な数値に変換した文字列の先頭部分を返します。次に例を示します。

 WRITE + "32 dollars and 64 cents"        // 32

文字列の先頭に数値文字がない場合、単項プラス演算子は、オペランドをゼロとします。次に例を示します。

 WRITE + "Thirty-two dollars and 64 cents" // 0

単項プラス演算子は、数値に対して何も作用しません。正数または負数の符号も変更しません。次に例を示します。

 SET x = -23
 WRITE " x: ", x,! // -23
 WRITE "+x: ",+x,! // -23

単項マイナス演算子 (-)

単項マイナス演算子 (-) は、数値として解釈されるオペランドの符号を反転します。次に例を示します。

 SET x = -60
 WRITE " x: ", x,! // -60
 WRITE "-x: ",-x,! // 60

オペランドが文字列値を持つ場合、単項マイナス演算子はその文字列を数値として解釈し、符号を反転します。数値は、上記の単項プラス演算子と同様の方法で解釈されます。次に例を示します。

 SET x = -23
 WRITE -"32 dollars and 64 cents" // -32

ObjectScript は、二項算術演算子より単項マイナス演算子を優先します。ObjectScript はまず数値式を検査し、単項マイナス演算子を実行します。その後、式を評価して結果を算出します。

以下の例では、ObjectScript は文字列を読み取り、数値 2 を検出するとそこで停止します。その後、単項マイナス演算子をその値に適用し、連結演算子 (_) を使用して、2 番目の文字列からの値 “Rats” を数値に結合します。

 WRITE -"2Cats"_"Rats" // -2Rats

数値式の絶対値を返すには、$ZABS 関数を使用します。

加算演算子 (+)

加算演算子は、2 つの数値として解釈されるオペランドの和を算出します。この演算子は、先行する有効なすべての数値文字をオペランドの数値として使用し、オペランドの数値の和を算出します。

以下の例は、2 つの数値リテラルを加算します。

 WRITE 2936.22 + 301.45 //  3237.67

以下の例は、2 つの定義済みローカル変数を加算します。

 SET x = 4
 SET y = 5
 WRITE "x + y = ",x + y // 9

以下の例は、先行する数字を持つ 2 つのオペランドに対し文字列算術を実行し、その結果を加算します。

 WRITE "4 Motorcycles" + "5 bicycles" // 9

以下の例は、数値として評価されたオペランドの先行ゼロが、演算子の結果に何も作用しないことを示します。

 WRITE "007" + 10 // 17

減算演算子 (-)

減算演算子は、数値として解釈される 2 つのオペランドの差を算出します。この演算子は、先行する有効なすべての数値文字をオペランドの数値として解釈し、減算後の剰余を算出します。

以下の例は、2 つの数値リテラルを減算します。

 WRITE 2936.22 - 301.45 // 2634.77

以下の例は、2 つの定義済みローカル変数の減算を実行します。

 SET x = 4
 SET y = 5
 WRITE "x - y = ",x - y // -1

以下の例は、先行する数字を持つ 2 つのオペランドに対して文字列算術を実行し、その結果を減算します。

 WRITE "8 apples" - "4 oranges" // 4

オペランドが先行数値文字を持たない場合、ObjectScript は、その値をゼロと見なします。次に例を示します。

 WRITE "8 apples" - "four oranges" // 8

乗算演算子 (*)

二項乗算演算子は、数値として解釈される 2 つのオペランドの積を算出します。この演算子も、オペランドの数値として先行する有効な数値文字をすべて使用して、積を算出します。

以下の例は、2 つの数値リテラルの乗算を実行します。

 WRITE 9 * 5.5 // 49.5

以下の例は、2 つの定義済みローカル変数の乗算を実行します。

 SET x = 4
 SET y = 5
 WRITE x * y // 20

以下の例は、先行する数字を持つ 2 つのオペランドに文字列算術を実行し、その結果を乗算します。

 WRITE "8 apples" * "4 oranges"  // 32

オペランドが先行数値文字を持たない場合、二項乗算演算子は、その値にゼロを割り当てます。

 WRITE "8 apples"*"four oranges" // 0

除算演算子 (/)

二項除算演算子は、数値として解釈される 2 つのオペランドの除算結果を算出します。この演算子も、オペランドの数値として先行する有効な数値文字をすべて使用して、商を算出します。

以下の例は、2 つの数値リテラルを除算します。

 WRITE 9 / 5.5 // 1.636363636363636364

以下の例は、2 つの定義済みローカル変数を除算します。

 SET x = 4
 SET y = 5
 WRITE x / y // .8

以下の例は、先行する数字を持つ 2 つのオペランドに文字列算術を実行し、その結果を除算します。

 WRITE "8 apples" / "4 oranges"  // 2

オペランドが先行数値文字を持たない場合、二項除算演算子は、その値をゼロと見なします。次に例を示します。

 WRITE "eight apples" / "4 oranges" // 0
 // "8 apples"/"four oranges" generates a <DIVIDE> error

上記の 2 番目の演算は無効です。ゼロによる数値の除算は許可されていないからです。ObjectScript は、<DIVIDE> エラー・メッセージを返します。

指数演算子 (**)

指数演算子は、右のオペランドを指数として左のオペランドをべき乗した値を算出します。

  • 0**0: ゼロのゼロ乗は 0 です。ただし、どちらかのオペランドが、IEEE 倍精度数の場合 (例えば、0**$DOUBLE(0) または $DOUBLE(0)**0)、ゼロのゼロ乗は 1 です。詳細は、"$DOUBLE 関数" を参照してください。

  • 0**n:ゼロの正数 n 乗はゼロです。0**$DOUBLE("INF") の場合も同様です。ゼロの負数乗を求めようとするとエラーが発生します。このときに生成されるエラーは、Caché の負数を指定した場合は <ILLEGAL VALUE>、$DOUBLE の負数を指定した場合は $DOUBLE です。

  • num**0:ゼロ以外の数値 (正または負) のゼロ乗は 1 です。$DOUBLE("INF")**0 の場合も同様です。

  • 1**n : 1 の任意の数値 (正、負、またはゼロ) 乗は 1 です。

  • -1**n: -1 のゼロ乗は 1、-1 の 1 乗および -1 の -1 乗は -1 です。1 より大きい指数の場合は、以下を参照してください。

  • num**n : 正数 (整数または小数) の任意の数値 (整数または小数、正または負) 乗は正数になります。

  • -num**n : 負数 (整数または小数) の偶数 (正または負) 乗は正数になります。負数 (整数または小数) の奇数 (正または負) 乗は負数になります。

  • -num**.n: 負数の小数乗を求めようとすると、<ILLEGAL VALUE> エラーが発生します。

  • $DOUBLE("INF")**n : 無限数 (正または負) のゼロ乗は 1、無限数 (正または負) の正数 (整数、小数、または INF) 乗は INF です。無限数 (正または負) の負数 (整数、小数、または INF) 乗は 0 です。

  • $DOUBLE("NAN") : 指数演算子のどちら側の NAN であっても、他方のオペランドの値に関係なく NAN が返ります。

非常に大きな指数を指定すると、値のオーバーフローやアンダーフローが発生することがあります。

  • num**nnn : 1 より大きな正または負の数の、大きな正数乗 (9**153-9.2**152 など) を求めようとすると、<MAXNUMBER> エラーが発生します。

  • num**-nnn : 1 より大きな正または負の数の、大きな負数乗 (9**-135-9.2**-134 など) はゼロになります。

  • .num**nnn : 1 未満の正または負の数の、大きな正数乗 (.22**196-.2**184 など) はゼロになります。

  • .num**-nnn : 1 未満の正または負の数の、大きな負数乗 (.22**-196-.2**-184 など) を求めようとすると、<MAXNUMBER> エラーが発生します。

Caché の数値として使用できる最大値を超える指数を使用すると、<MAXNUMBER> エラーが発生するか、自動的に IEEE 倍精度浮動小数点数に変換されます。この自動変換は、%SYSTEM.ProcessOpens in a new tab クラスの TruncateOverflow()Opens in a new tab メソッドを使用してプロセスごとに指定するか、または Config.MiscellaneousOpens in a new tab クラスの TruncateOverflowOpens in a new tab プロパティを使用してシステム全体で指定します。詳細は、"$DOUBLE 関数" を参照してください。

以下の例は、2 つの数値リテラルをべき乗します。

 WRITE "9 ** 2 = ",9 ** 2,! // 81
 WRITE "9 ** -2 = ",9 ** -2,! // .01234567901234567901
 WRITE "9 ** 2.5 = ",9 ** 2.5,! // 242.9999999994422343

以下の例は、2 つの定義済みローカル変数をべき乗します。

 SET x = 4, y = 3
 WRITE "x ** y = ",x ** y,! // 64

以下の例は、文字列算術演算を実行します。指数演算子も、オペランドの値として先行する数値文字をすべて使用して、結果を算出します。

 WRITE "4 apples" ** "3 oranges" // 64

オペランドが先行数値文字を持たない場合、指数演算子は、その値をゼロと見なします。

以下の例は、指数を使用した数値の平方根の算出方法です。

 WRITE 256 ** .5 // 16

べき乗計算は、$ZPOWER 関数を使用しても可能です。

整数除算演算子 ( \ )

整数除算演算子は、左のオペランドを右のオペランドで除算した整数の結果を算出します。剰余を返さず、結果も丸めません。

以下の例は、2 つの整数オペランドを整数除算します。ObjectScript は、結果の小数部分を返しません。

 WRITE "355 \ 113 = ", 355 \ 113 // 3

以下の例は、文字列算術演算を実行します。整数除算演算子も、オペランドの値として先行する数値文字をすべて使用して、整数の結果を算出します。

 WRITE "8 Apples" \ "3.1 oranges" // 2

オペランドが先行数値文字を持たない場合、ObjectScript は、その値をゼロと見なします。整数をゼロで除算しようとすると、ObjectScript は <DIVIDE> エラーを返します。

モジュロ演算子 (#)

モジュロ演算子は、数値として解釈される 2 つのオペランドにモジュロ演算の結果を算出します。2 つのオペランドが正の場合、モジュロ演算の結果は、右のオペランドで左のオペランドを整数除算した剰余です。

以下の例は、数値リテラルにモジュロ演算を実行し、その剰余を返します。

 WRITE "37 # 10 = ",37 # 10,! // 7
 WRITE "12.5 # 3.2 = ",12.5 # 3.2,! // 2.9

以下の例は、文字列算術演算を実行します。文字列の演算を行う場合、モジュロ演算子が適用される前に、文字列は数値に変換されます ("変数のタイプと変換" のセクションで説明されています)。したがって、以下の 2 つの式は同一です。

 WRITE "8 apples" # "3 oranges",!  // 2
 WRITE 8 # 3 // 2

Caché は、先行数値文字のない文字列を 0 と解釈するため、このようなオペランドを右側に使用すると、<DIVIDE> エラーが発生します。

論理比較演算子

論理比較演算子は、オペランド値を比較し、True (1) か False (0) のブーリアン値を返します。

単項否定演算子

単項否定演算子は、ブーリアン型オペランドの真偽値を反転します。オペランドが True (1) の場合、単項否定演算子は False (0) になります。オペランドが False (0) の場合、単項否定演算子は True (1) になります。

例えば、以下の文は False (0) の結果を返します。

  SET x=0
  WRITE x

一方、以下の文は True (1) を返します。

  SET x=0
  WRITE 'x

比較演算子で単項否定演算子を使用すると、演算子が実行する演算の意味が反転します。事実上、演算の結果が反転されます。例えば、以下の文は False (0) の結果を返します。

  WRITE 3>5

しかし、以下の例は True (1) の結果を表示します。

  WRITE 3'>5

論理演算子の優先順位

ObjectScript は、厳格に演算子を左から右へ評価するため、その他の演算子が関与する論理比較では、必要な優先順位を実現するために、演算をグループ化する括弧を使用する必要があります。例えば、以下のプログラムで True (1) を返すために、二項論理和演算 (!) テストが要求されます。

  SET x=1,y=0
  IF x=1 ! y=0 {WRITE "TRUE"}
  ELSE {WRITE "FALSE" } 
  // Returns 0 (FALSE), due to evaluation order

しかし、この論理比較を適切に実行するには、その他の演算を入れ子にする括弧を使用する必要があります。以下の例では、期待される結果が得られます。

  SET x=1,y=0
  IF (x=1) ! (y=0) {WRITE "TRUE"}
  ELSE {WRITE "FALSE" } 
  // Returns 1 (TRUE)

二項論理積演算子

二項論理積演算子は、オペランドの両方の値が True (1) であるかどうかを判断します。オペランドが両方とも True の場合 (つまり、数値として計算した場合、ゼロ以外の値となる)、ObjectScript は、True (1) を返します。それ以外の場合、False (0) を返します。

二項論理積演算子には、& と && という 2 つの形式があります。

  • & 演算子は、両方のオペランドを評価し、いずれかのオペランドの値がゼロの場合、False (0) を返します。それ以外は True (1) を返します。

  • && 演算子は、左のオペランドを評価し、そのオペランドの値がゼロの場合、False (0) を返します。左のオペランドがゼロ以外の場合にのみ、&& 演算子は右のオペランドを評価します。右のオペランドの評価がゼロの場合、False (0) を返します。それ以外は True (1) を返します。

以下の例は、2 つのゼロ以外のオペランドを True と評価して True (1) を返します。

 SET A=-4,B=1
 WRITE A&B // TRUE (1)

これは、1 を返します。

 SET A=-4,B=1
 WRITE A&&B // TRUE (1)

これは、1 を返します。

以下の例は、True と False のオペランドをそれぞれ評価して False (0) を返します。

 SET A=1,B=0
 WRITE "A = ",A,!
 WRITE "B = ",B,!
 WRITE "A&B = ",A&B,! // FALSE (0)
 SET A=1,B=0
 WRITE "A&&B = ",A&&B,! // FALSE (0)

上記は、両方とも False (0) を返します。

以下の例は、“&” 演算子と “&&” 演算子の違いを示します。以下の例では、左のオペランドは False (0) と評価され、右のオペランドは定義されていません。この場合、“&” と “&&” 演算子の結果が異なることに注意してください。

  • “&” 演算子は両方のオペランドを評価し、<UNDEFINED> エラーを生じます。

      TRY {
           KILL B
           SET A=0
           WRITE "variable A defined?: ",$DATA(A),!
           WRITE "variable B defined?: ",$DATA(B),!
           WRITE A&B
           WRITE !,"Success"
           RETURN
          }
      CATCH exp
      {
          IF 1=exp.%IsA("%Exception.SystemException") {
             WRITE !,"System exception",!
             WRITE "Name: ",$ZCVT(exp.Name,"O","HTML"),!
             WRITE "Data: ",exp.Data,!!
          }
          ELSE { WRITE "not a system exception"}
      }
  • “&&” 演算子は左のオペランドのみを評価し、False (0) を返します。

      TRY {
           KILL B
           SET A=0
           WRITE "variable A defined?: ",$DATA(A),!
           WRITE "variable B defined?: ",$DATA(B),!
           WRITE A&&B
           WRITE !,"Success"
           RETURN
          }
      CATCH exp
      {
          IF 1=exp.%IsA("%Exception.SystemException") {
             WRITE !,"System exception",!
             WRITE "Name: ",$ZCVT(exp.Name,"O","HTML"),!
             WRITE "Data: ",exp.Data,!!
          }
          ELSE { WRITE "not a system exception"}
      }

論理積否定演算 (NAND)

以下に相当するいずれかの形式で、二項論理積演算子 (&) と単項否定演算子を併用して、論理積否定演算 (NAND) 演算を指定できます。

operand '& operand  '(operand & operand)

論理積否定演算は、両方のオペランドに適用された & 二項論理積演算の論理値を反転します。いずれかのオペランド、もしくは両方のオペランドが False である場合、True (1) を返します。両方のオペランドが True の場合、False を返します。

&& 二項論理積演算子の前に、単項否定演算子を付けることはできません。“'&&” という形式はサポートされていません。ただし、以下の形式はサポートされています。

'(operand && operand)

以下の例では、2 つの対応する論理積否定演算を実行します。各演算で、1 つの False (0) と 1 つの True (1) のオペランドが評価され、True (1) の値が返されます。

 SET A=0,B=1
 WRITE !,A'&B   // Returns 1
 WRITE !,'(A&B) // Returns 1

以下の例では、&& 二項論理積演算を実行することにより、論理積否定演算を実行した後、単項否定演算を使用して、結果を反転させます。&& 演算は、最初のオペランドをテストし、ブーリアン値が False (0) のため、&& は 2 番目のオペランドをテストしません。単項否定演算は、式が True (1) を返すように、結果のブーリアン値を反転させます。

 SET A=0
 WRITE !,'(A&&B)   // Returns 1

二項論理和演算子

二項論理和演算子は、いずれか一方のオペランドが True の値を持つ場合、あるいは両方のオペランドが True (1) の値を持つ場合、True (1) を返します。二項論理和演算子は、両方のオペランドが False (0) の場合にのみ False (0) を返します。

二項論理積演算子には、! (感嘆符) および || (2 本の縦バー) の 2 つの形式があります。

  • ! 演算子は、両方のオペランドを評価し、両方のオペランドの値がゼロの場合、False (0) を返します。それ以外は True (1) を返します。

  • || 演算子は、左のオペランドを評価します。左のオペランドがゼロ以外の値に評価された場合、|| 演算子は、右のオペランドを評価せずに True (1) を返します。左のオペランドがゼロの場合にのみ、|| 演算子は、右のオペランドを評価します。右のオペランドがゼロの場合、False (0) を返します。それ以外は True (1) を返します。

以下の例は、2 つの True の (ゼロではない) オペランドに二項論理和演算を実行し、True の結果を返します。

 SET A=5,B=7
 WRITE "A!B = ",A!B,! 
 SET A=5,B=7
 WRITE "A||B = ",A||B,!

上記は、両方とも True (1) を返します。

以下の例は、False のオペランドと True のオペランドに二項論理和演算を実行し、True の結果を返します。

 SET A=0,B=7
 WRITE "A!B = ",A!B,!
 SET A=0,B=7
 WRITE "A||B = ",A||B,!

上記は、両方とも True (1) を返します。

以下の例は、2 つの False のオペランドを評価し、False の結果を返します。

 SET A=0,B=0
 WRITE "A!B = ",A!B,!
 SET A=0,B=0
 WRITE "A||B = ",A||B,!

上記は、両方とも False (0) を返します。

論理和否定演算 (NOR)

論理和否定演算 (NOR) は、以下のいずれかの等価形式で、単項否定演算子と二項論理和演算子 ! を組み合わせて記述できます。

operand '! operand '(operand ! operand)

論理和否定演算は、両方のオペランドが False の場合、True (1) の結果を返します。どちらか一方のオペランドが True の場合、あるいは両方のオペランドが True の場合、False (0) の結果を返します。

|| 二項論理和演算子の前に、単項否定演算子を付けることはできません。“'||” という形式はサポートされていません。ただし、以下の形式はサポートされています。

'(operand || operand)

以下の論理和否定演算の例は、2 つの False のオペランドを評価して、True の結果を返します。

 SET A=0,B=0
 WRITE "A'!B = ",A'!B   // Returns 1
 SET A=0,B=0
 WRITE "'(A!B) = ",'(A!B)   // Returns 1

以下の論理和否定演算の例は、1 つの True のオペランドと 1 つの False のオペランドを評価して、False の結果を返します。

 SET A=0,B=1
 WRITE "A'!B = ",A'!B   // Returns 0
 SET A=0,B=1
 WRITE "'(A!B) = ",'(A!B)   // Returns 0

以下の論理和否定演算の例では、左のオペランドを評価し、その結果が True (1) なので、右のオペランドを評価しません。単項否定演算は、式が False (0) を返すように、結果のブーリアン値を反転させます。

 SET A=1
 WRITE "'(A||B) = ",'(A||B)   // Returns 0

文字列連結演算子

文字列連結演算子 (_) は、そのオペランドを文字列と解釈し、文字列値を返す二項 (2 オペランド) 演算子です。

連結演算子を使用して、文字列リテラル、数字、式、変数を結合します。以下の形式をとります。

operand_operand

連結演算子は、右のオペランドを左のオペランドの後に結合させた文字列を結果として返します。連結演算子は、そのオペランドを特に解釈せず、文字列値として扱います。

以下の例は、2 つの文字列を結合します。

  WRITE "High"_"chair"

上記は、“Highchair” を返します。

ある数値リテラルを別の数値リテラル、または非数値文字列に連結すると、Caché は最初にそれぞれの数値をキャノニック形式に変換します。以下の例は、2 つの数値リテラルを結合します。

  WRITE 7.00_+008

これは、78 を返します。

以下の例は、数値リテラルと数値文字列を結合します。

  WRITE ++7.00_"+007"

これは、文字列 7+007 を返します。

以下の例は、2 つの文字列と NULL 文字列を結合します。

 SET A="ABC"_""_"DEF" 
 WRITE A

これは、“ABCDEF” を返します。

NULL 文字列は、文字列の長さに影響しないため、無数の NULL 文字列を文字列に結合できます。

文字列の最大サイズは構成可能です。長い文字列を有効にすると、文字列の最大サイズは 3,641,144 文字になります。長い文字列を有効にしていない場合、最大文字列サイズは 32,767 文字です。既定では長い文字列が有効になっています。“データ型とデータ値” の章の “長い文字列” のセクションを参照してください。

非常に長い文字列が作成される連結によって、連結された文字列が長すぎて変数に保存できない場合、<STORE>E エラーが発生する場合があります。<STORE> エラーが発生した場合、連結によって拡大された変数は、連結前のその値を保持します。

連結エンコード文字列

Caché 文字列には、それらの文字列を結合できるかどうかを制限できる内部的なエンコードが含まれるものがあります。

  • ビット文字列は、別のビット文字列、ビット文字列でない文字列、空の文字列 ("") のどれとであれ、結合できません。これを実行しようとすると、生成される文字列を使用するときに、<INVALID BIT STRING> エラーが返されます。

  • リスト構造文字列は、別のリスト構造文字列または空の文字列 ("") と結合できます。しかし、リスト以外の文字列とは連結できません。これを実行しようとすると、生成される文字列を使用するときに、<LIST> エラーが返されます。

  • JSON 文字列は、別の JSON 文字列、JSON 文字列でない文字列、空の文字列 ("") のどれとであれ、結合できません。これを実行しようとすると、生成される文字列を使用するときに、<INVALID OREF> エラーが返されます。

数値関係演算子

文字列関係演算子と数値関係演算子という、2 種類の関係演算子があります。数値関係演算子は、オペランドの数値を使用してブーリアン値の結果を返します。文字列に対する演算では、“文字列から数値への変換” のセクションに説明があるルールに従い、文字列は数値関係演算子によってそれぞれが該当する数値として扱われます。

数値関係演算子を非数値文字列の比較で使用しないでください

IEEE の倍精度小数 ($DOUBLE 数) と Caché 標準の浮動小数点数 ($DECIMAL 数) の間では、値を丸めずに、正確な値で比較が行われます。$DOUBLE 数と $DECIMAL 数の等値比較は、予期しない結果が発生することが多いので避ける必要があります。IEEE 倍精度数を含む算術演算子の詳細は、"Caché プログラミング入門ガイド" の付録 “インターシステムズ・アプリケーションでの数値の計算” を参照してください。

二項より小さい関係演算子

二項より小さい関係演算子は、左のオペランドが右のオペランドより数値的に小さいかどうかをテストします。ObjectScript は、両方のオペランドを数値的に評価して、左のオペランドが右のオペランドより数値的に小さい場合、True (1) のブーリアン値を返します。左のオペランドが右のオペランドと数値的に等しい、または大きい場合、False (0) のブーリアン値を返します。次に例を示します。

 WRITE 9 < 6

これは、0 を返します。

 WRITE 22 < 100

これは、1 を返します。

二項より大きい関係演算子

二項より大きい関係演算子は、左のオペランドが右のオペランドより数値的に大きいかどうかを判断します。ObjectScript は、2 つのオペランドを数値的に評価し、左のオペランドが右のオペランドより数値的に大きい場合、True (1) を返します。左のオペランドが右のオペランドと数値的に等しい、または小さい場合、False (0) の論理値を返します。次に例を示します。

 WRITE 15 > 15

これは、0 を返します。

 WRITE 22 > 100

これは、0 を返します。

以上関係演算子

以下のようにして、以上関係演算子を記述できます。

  • 二項より大きい関係演算子 (>) と等値演算子 (=) を結合します。2 つの演算子のどちらかが TRUE を返す場合、これらの演算子の組み合わせによって TRUE が返されます。

  • 二項より小さい関係演算子 (<) と共に単項否定演算子 (') を使用します。共に使用する 2 つの演算子は、二項より小さい関係演算子の真偽値を反転します。

ObjectScript は、左のオペランドが右のオペランドより数値的に大きい、または等しい場合、True (1) の結果を返します。左のオペランドが右のオペランドよりも数値的に小さい場合、False (0) の結果を返します。

以下のいずれかの方法で、以上関係演算を記述できます。

operand_A >= operand_B
operand_A '< operand_B
'(operand_A < operand_B)

以下関係演算子

以下のようにして、以下関係演算子を記述できます。

  • 二項より小さい関係演算子 (<) と等値演算子 (=) を結合します。2 つの演算子のどちらかが TRUE を返す場合、これらの演算子の組み合わせによって TRUE が返されます。

  • 二項より大きい関係演算子 (>) と共に単項否定演算子 () を使用します。共に使用する 2 つの演算子は、二項より大きい関係演算子の論理値を反転します。

ObjectScript は、左のオペランドが右のオペランドより数値的に小さい、または等しい場合、True (1) の結果を返します。左のオペランドが右のオペランドよりも数値的に大きい場合、False (0) の結果を返します。

以下のいずれか方法で、以下関係演算を記述できます。

operand_A <= operand_B
operand_A '> operand_B
'(operand_A > operand_B)

以下の例は、以下関係演算で 2 つの変数をテストします。両方の変数の値が等しいため、結果は True となります。

 SET A="55",B="55" 
 WRITE A'>B

これは、1 を返します。

文字列関係演算子

数値関係演算子と文字列関係演算子という、2 種類の関係演算子があります。文字列関係演算子は、オペランドを文字列として解釈してブーリアン値の結果を返します。文字列関係演算子は、否定論理演算子 (') を先頭に付けて、論理結果を反転することができます。

二項等値演算子

二項等値演算子は、2 つのオペランドが文字列として等しいかを判断します。二項等値演算子を 2 つの文字列で実行すると、ObjectScript は、2 つのオペランドの文字順序が同一で、スペースを含め他の異なる文字を持たない同一の文字列の場合に True (1) を返します。それ以外の場合は False (0) を返します。次に例を示します。

 WRITE "SEVEN"="SEVEN"

上記は、True (1) を返します。

二項等値演算子は、どちらのオペランドも数値的に解釈しません。例えば、以下の文は、2 つのオペランドが数値的には等価ですが、False (0) を返します。

 WRITE "007"="7"

上記は、False (0) を返します。

両方のオペランドが数値である場合、二項等値演算子を使用して、数値的に等しいかどうかを判断できます。次に例を示します。

 WRITE 007=7

上記は、True (1) を返します。

また、単項プラス演算子を使用して、強制的に数値変換を実行できます。次に例を示します。

 WRITE +"007"="7"

上記は、True (1) を返します。

2 つのオペランドのタイプが異なる場合、両方のオペランドが文字列に変換され、それらの文字列が比較されます。 文字列への変換時に、丸めおよび有効桁数のために誤差が生じる可能性があります。次に例を示します。

 WRITE "007"=7,!
  // converts 7 to "7", so FALSE (0)
 WRITE 007="7",!
  // converts 007 to "7", so TRUE (1)
 WRITE 17.1=$DOUBLE(17.1),!
  // converts both numbers to "17.1", so TRUE (1)
 WRITE 1.2345678901234567=$DOUBLE(1.2345678901234567),!
  // compares "1.2345678901234567" to "1.23456789012346", so FALSE (0)

不等関係演算

不等関係演算は、単項否定演算子と二項等値演算子を併用して指定できます。以下の 2 とおりの方法で、不等関係演算を記述できます。

operand '= operand
'(operand = operand)

不等関係演算は、二項等値演算子を両方のオペランドに適用した場合の論理値を反転します。2 つのオペランドが等しくない場合、結果は True (1) となります。2 つのオペランドが等しい場合、結果は False (0) となります。

二項包含関係演算子

二項包含関係子は、右のオペランドの一連の文字が、左の文字の部分文字列であるかを判断します。左のオペランドが、右のオペランドの文字列を含んでいる場合、結果は True (1) となります。左のオペランドが、右のオペランドの文字列を含んでいない場合、結果は False (0) となります。右のオペランドが NULL 文字列の場合、結果は常に True となります。

以下の例は、L の文字列が S の文字列を含むかどうかを判断します。L は S を含んでいるため、結果は True (1) となります。

 SET L="Steam Locomotive",S="Steam"
 WRITE L[S

上記は、True (1) を返します。

以下の例は、P の文字列が S の文字列を含むかどうかを判断します。文字列中の文字の並びが異なるため (P はピリオド、S は感嘆符を持つ)、結果は False (0) となります。

 SET P="Let's play.",S="Let's play!"
 WRITE P[S

上記は、False (0) を返します。

非包含演算

非包含演算は、以下のいずれかの等価形式で、二項包含関係演算子と単項否定演算子を使用して記述できます。

operand A '[ operand B

'(operand A [ operand B)

非包含演算は、オペランド A がオペランド B で表される文字列を含まない場合に True を返し、オペランド B で表される文字列を含む場合は False を返します。

 SET P="Beatles", S="Mick Jagger"
 WRITE P'[S

これは、1 を返します。

二項後続関係演算子

二項後続関係演算子は、左のオペランドの文字が、ASCII 文字順で右のオペランドの文字の後に来るかどうかを判断します。二項後続関係演算子は、両方の文字列が、それぞれの最左端の文字から始まるものとします。このテストは、以下のいずれかの場合に終了します。

  • 左のオペランドの中に、対応する右のオペランドの文字と異なる文字が発見された場合

  • いずれかのオペランドに、比較する文字がない場合

ObjectScript は、左のオペランド内の最初の一意の文字が、右のオペランド内の対応する文字よりも高い ASCII 値を持つ場合 (つまり、左のオペランドの文字が、右のオペランドの文字よりも ASCII 文字順で後に来る場合)、True の値を返します。右のオペランドが左のオペランドより短いが、それ以外は等しい場合も、ObjectScript は True の値を返します。

ObjectScript は、以下のいずれかの条件が当てはまる場合、False の値を返します。

  • 左のオペランド内の最初の一意の文字が、右のオペランド内の対応する文字よりも低い ASCII 値を持つ場合

  • 左のオペランドが右のオペランドと同一の場合

  • 左のオペランドが右のオペランドよりも短いが、それ以外は同一の場合

以下の例は、文字列 LAMPOON が、ASCII 文字順で文字列 LAMP の後に来るかどうかを判断します。結果は True です。

 WRITE "LAMPOON"]"LAMP"

上記は、True (1) を返します。

以下の例は、B の文字列が A の文字列の後に来るかどうかを判断します。ASCII 文字順では、BO が BL の後に来るため結果は True です。

 SET A="BLUE",B="BOY" 
 WRITE B]A

上記は、True (1) を返します。

非後続演算

非後続演算は、以下のどちらかの等価形式で、二項後続関係演算子と単項否定演算子を使用して記述できます。

operand A ']operand B 
'(operand A ] operand B) 

非後続演算は、両方のオペランドのすべての文字が同一である場合、あるいはオペランド A の最初の一意の文字が、オペランド B の対応する文字よりも低い ASCII 値を持つ場合、True の値を返します。また、オペランド A の最初の一意の文字が、オペランド B の対応する文字よりも高い ASCII 値を持つ場合、False の値を返します。

以下の例では、CDE の C は ABC の A の後ろに来るため、結果は False となります。

 WRITE "CDE"']"ABC",!
 WRITE '("CDE"]"ABC")

上記は、False (0) を返します。

二項前後関係演算子

二項前後関係演算子は、左のオペランドが数値添え字の照合順序で右のオペランドの後に順番に並んでいるかを判定します。数値照合順序では、NULL 文字列が最初に置かれます。次に負数から数値順に並べたキャノニック形式の数値、ゼロ、整数と続き、最後に数値以外の値が置かれます。

二項前後関係演算子は、照合順序上で第 1 オペランドが第 2 オペランドよりも後に位置している場合に True (1) を、それ以外の場合に False (0) を返します。次に例を示します。

 WRITE 122]]2

上記は、True (1) を返します。

 WRITE "LAMPOON"]]"LAMP"

上記は、True (1) を返します。

非前後関係演算

非前後関係演算は、以下のいずれかの等価形式でも、二項後続関係演算子と共に単項否定演算子を使用して記述できます。

operand A ']] operand B
'(operand A ]] operand B)

オペランド A がオペランド B と同一である場合、あるいはオペランド B が、オペランド A の後に順番に並んでいる場合、ObjectScript は、True の値を返します。オペランド A がオペランド B の後ろに順番に並んでいる場合、False の値を返します。

パターン・マッチング

Caché では、以下の 2 系統のパターン・マッチングをサポートしています。

  • ObjectScript のパターン・マッチング : ここで説明するパターン・マッチングは、疑問符 (?) またはその否定 ('?) でパターン文字列の先頭部を定める構文です。

  • 正規表現 : 多くのソフトウェア・ベンダよりサポートされる (バリアントを用いた) パターン・マッチ構文です。正規表現は、$LOCATE および $MATCH 関数と %Regex.MatcherOpens in a new tab クラスのメソッドで使用できます。それらについては、このドキュメントの個別の章にて説明しています。

これらのパターン・マッチング・システムは完全に別個のものです。それぞれのパターン・マッチング・システムはその独自のコンテキストでのみ使用できます。ただし、以下の例で示すように、論理 AND および OR 構文を使用して、異なるパターン・マッチング・システムからパターン・マッチング・テストを組み合わせることは可能です。

  SET var = "abcDEf"
  IF (var ?.e2U.e) && $MATCH(var, "^.{3,7}") { WRITE "It's a match!"}
  ELSE { WRITE "No match"}

ObjectScript のパターンは、文字列が 2 連続の大文字を含んでいるかどうかを判断します。正規表現のパターンは、文字列が 3 ~ 7 文字かどうかを判断します。

ObjectScript のパターン・マッチング

ObjectScript のパターン・マッチング演算子は、左オペランドの文字が、その右オペランドのパターンと正確に一致しているかどうかを判断します。この演算子はブーリアン値を返します。パターン・マッチング演算子は、パターンが左オペランドの文字パターンに一致した場合に True (1) の結果を返します。また、一致しなかった場合は False (0) の結果を返します。

以下の例は、文字列 ssn に有効な米国社会保証番号 (数字 3 桁、ハイフン、数字 2 桁、ハイフン、数字 4 桁) が含まれているかどうかをテストします。

 SET ssn="123-45-6789"
 SET match = ssn    ?3N1"-"2N1"-"4N
 WRITE match

左オペランド (テスト値) と右オペランド (パターン) は、右オペランドの先頭の ? で区別されます。これら 2 つのオペランドは、以下の等価プログラムの例で示すように、1 つ以上の空白スペースで区切られる場合、もしくは空白スペースで区切られない場合もあります。

 SET ssn="123-45-6789"
 SET match = ssn?3N1"-"2N1"-"4N
 WRITE match

? 演算子の後に空白が入ることはできません。パターン内の空白は引用符で囲まれた文字列内に置く必要があり、パターンの一部として解釈されます。

パターン・マッチング演算の一般的な形式は以下のとおりです。

operand?pattern
operand パターンのテスト対象となる文字群である、文字列や数字として評価される式です。
pattern ? 記号 (不一致テストの場合は ‘?) で始まるパターン・マッチング・シーケンスです。このパターン・シーケンスは、1 つ以上の pattern-elements (パターン要素) の列、あるいは 1 つ以上の pattern-elements の列として評価される間接参照のいずれかとなります。

pattern-element は以下のいずれかで構成されます。

  • repeat-count pattern-codes

  • repeat-count literal-string

  • repeat-count alternation

repeat-count リピート・カウント — パターンの各インスタンスをマッチさせる具体的な回数です。repeat-count は、整数またはピリオド・ワイルドカード文字 (.) に評価できる文字です。任意の回数を指定するには、ピリオドを使用します。
pattern-codes 1 つまたは複数のパターン・コード。複数のコードを指定した場合は、それらのコードのいずれかと一致するとパターンの条件が満たされます。
literal-string 二重引用符で囲まれたリテラル文字列。
alternation 一連の pattern-element。この pattern-element のいずれかを選択して、オペランド文字列のセグメントとのパターン・マッチングに使用します。これにより、パターン指定で論理 OR 機能が得られます。

特定の文字や文字列を比較する場合、二重引用符で囲んだリテラル文字列をパターンで使用します。他の状況では、ObjectScript が提供する特殊なパターン・コードを使用します。特定のパターン・コードに関連付けられる文字は、(ある程度の) ロケール依存となります。以下のテーブルは、使用可能なパターン・コードとその意味です。

パターン・コード
Code 意味
A 任意のアルファベットの大文字または小文字に一致。ロケールの 8 ビット文字セットは、アルファベット文字が何であるかを定義します。英語のロケール (Latin-1 文字セットに基づく) の場合、これには ASCII 値 65 ~ 90 (A ~ Z)、97 ~ 122 (a ~ z)、170、181、186、192 ~ 214、216 ~ 246、および 248 ~ 255 が含まれます。
C 任意の ASCII 制御文字 (ASCII 値の 0 から 31 までと拡張 ASCII 値の 127 から 159 まで) と一致。
E 出力不能文字、空白文字、および制御文字を含む任意の文字と一致。
L 任意のアルファベットの小文字に一致。ロケールの 8 ビット文字セットは、小文字が何であるかを定義します。英語のロケール (Latin-1 文字セットに基づく) の場合、これには ASCII 値 97 ~ 122 (a ~ z)、170、181、186、223 ~ 246、および 248 ~ 255 が含まれます。
N 10 個の ASCII 数字 (0 から 9、ASCII 48 から 57) のいずれとも一致。
P 任意の句読点文字に一致。ロケールの文字セットは、拡張 (8 ビット) ASCII 文字セットに対して、句読点文字が何であるかを定義します。英語のロケール (Latin-1 文字セットに基づく) の場合、これには ASCII 値 32 ~ 47、58 ~ 64、91 ~ 96、123 ~ 126、160 ~ 169、171 ~ 177、180、182 ~ 184、187、191、215、および 247 が含まれます。
U 任意のアルファベットの大文字に一致。ロケールの 8 ビット文字セットは、大文字が何であるかを定義します。英語のロケール (Latin-1 文字セットに基づく) の場合、これには ASCII 値 65 ~ 90 (A ~ Z)、192 ~ 214、および 216 ~ 222 が含まれます。

R

B

M

キリル 8 ビット・アルファベット文字のマッピングに一致。R は任意のキリル文字 (ASCII 値の 192 から 255 まで) と一致します。B は大文字のキリル文字 (ASCII 値の 192 から 223 まで) と一致します。M は小文字のキリル文字 (ASCII 値の 224 から 255 まで) と一致します。これらのパターン・コードは、Russian 8 ビット Windows ロケール (ruw8) のみで意味を持ちます。他のロケールでは、実行には成功しますが、いずれの文字とも一致しません。
ZFWCHARZ 日本語の全角文字セットのいずれの文字とも一致。ZFWCHARZ は、漢字などの全角文字や、一部のターミナル・エミュレータによって表示されたときに二重セルを占有する多くの漢字以外の文字に一致します。また、ZFWCHARZ は JIS2004 標準で定義された 303 のサロゲート・ペア文字とも一致して、各サロゲート・ペアを単一文字として扱います。例えば、サロゲート・ペア文字 $WC(131083) は、?1ZFWCHARZ に一致します。このパターン・マッチング・コードには、日本語ロケールが必要となります。
ZHWKATAZ 日本語の半角かな文字セットのいずれの文字とも一致。これらは、Unicode 値 65377 (FF61) ~ 65439 (FF9F) までです。このパターン・マッチング・コードには、日本語ロケールが必要となります。

パターン・コードは大文字と小文字を区別しません。大文字と小文字いずれも指定できます。例えば、?5N と ?5n は等価です。複数のパターン・コードを指定して、特定の文字または文字列に一致させることができます。例えば、?1NU は数字または大文字のいずれかに一致します。

"Caché 用語集" に記載のとおり、ASCII 文字セットとは、文字数が少ない 7 ビット文字セットではなく、拡張された 8 ビット文字セットを指しています。

Note:

二重引用符文字と一致するパターンは、異なる NLS ロケールを使用して Caché 実装からデータが提供されている場合に特に、不整合な結果を生じる場合があります。まっすぐな二重引用符文字 ($CHAR(34) = ") は、句読点文字として照合されます。方向性のある二重引用符文字 (巻いている引用符) は、句読点文字として照合されません。8 ビットの方向性のある二重引用符文字 ($CHAR(147) = “ と $CHAR(148) = ”) は、制御文字として照合されます。Unicode の方向性のある二重引用符文字 ($CHAR(8220) = “ と $CHAR(8221) = ”) は、句読点文字としても、制御文字としても照合されません。

パターン・マッチング演算子は、二項包含関係演算子 ([) とは異なります。二項包含関係演算子は、左辺のオペランドの部分文字列が右辺のオペランドと一致する場合も、True (1) を返します。また、二項包含関係式は、パターン・マッチング演算子で使用できる一連のオプションを提供しません。二項包含関係式では、単一の文字列のみ右辺のオペランドで使用できます。特殊コードは使用できません。

例えば、変数 var2 に値 “abc” が含まれているとします。以下のパターン・マッチ式を考えてみます。

 SET match = var2?2L

var2 は、2 つではなく 3 つの小文字を持っているため、match は False (0) の結果を返します。

以下に、基本的なパターン・マッチングの例を示します。

PatternMatchTest
 SET var = "O"
 WRITE "Is the letter O",!

 WRITE "...an alphabetic character? "
 WRITE var?1A,!

 WRITE "...a numeric character? "
 WRITE var?1N,!

 WRITE "...an alphabetic or ",!,"  a numeric character? "
 WRITE var?1AN,!

 WRITE "...an alphabetic or ",!,"  a ZENKAKU Kanji character? "
 WRITE var?1AZFWCHARZ,!

 WRITE "...a numeric or ",!,"  a HANKAKU Kana character? "
 WRITE var?1ZHWKATAZN

以下の項目を指定して、パターン・コードの範囲を拡張できます。

パターンの発生回数の指定

以下の形式で、目的のオペランドで パターン が繰り返し発生できる回数の範囲を定義します。

n.n

1 番目の n は範囲の下限を、2 番目の n は上限を定義します。

以下の例では、変数 var3 に文字列 “AB” の複数のコピーが含まれていて、その他の文字は含まれていないものとします。1.4 は “AB” が 1 ~ 4 回出現すると認識されていることを示します。

 SET match = var3?1.4"AB"

var3 =“ABABAB” の場合、この式は、var3 に “AB” が 3 つしか含まれていない場合でも、True (1) の結果を返します。

別の例として、以下の式を考えてみます。

 SET match = var4?1.6A

この式は、var4 に 1 個から 6 個までの英文字が含まれているかどうかをチェックします。var4 に英文字がまったく含まれていないか、7 文字以上の英文字が含まれているか、または英文字以外の文字が含まれている場合、False (0) の結果を返します。

どちらか一方の n を省略すると、ObjectScript は既定値を提供します。1 番目の n の既定値はゼロ (0) です。2 番目の n の既定値は任意の値です。以下の例を考えてみます。

 SET match = var5?.E1"AB".E

この例は、var5 に、パターン文字列 “AB” が少なくとも 1 つ含まれている限り、True (1) を返します。

複数パターンの指定

複数パターンを定義するには、任意の長さで n とパターンを組み合わせます。以下の例を考えてみます。

 SET match = date?2N1"/"2N1"/"2N

この式は、mm/dd/yy 形式で日付値をチェックします。文字列 “4/27/98” の場合、月の値が 1 桁なので False (0) を返します。1 桁の月と 2 桁の月の両方を検出するには、以下のように変更します。

 SET match = date?1.2N1"/"2N1"/"2N

1 番目のパターン・マッチング (1.2N) は、1 桁または 2 桁の数字を受け取ります。前述のように、繰り返し回数の範囲を定義するため、オプションの小数点 (.) を使用します。

組み合わせパターンの指定

以下の形式を使用して、組み合わせパターンを定義します。

Pattern1Pattern2

パターンの組み合わせで、pattern1pattern2 が続く配列との比較で、目的のオペランドをチェックします。例えば、以下の式を考えてみます。

 SET match = value?3N.4L

この式は、3 桁の数字の後ろに、0 から 4 つの小文字の英字が続いているかどうかのパターンをチェックします。目的のオペランドにパターンの組み合わせと同じものが 1 つ含まれている場合にのみ True (1) を返します。例えば、文字列 “345g” と “345gfij” は一致しますが、“345gfijhkbc” と “345gfij276hkbc” は一致しません。

不確定パターンの指定

以下の形式を使用して、不確定パターンを指定します。

.pattern

不確定パターンを使用して、目的のオペランドは、pattern の繰り返しをチェックします。繰り返しの数は (ゼロ回を含め) 指定されません。例えば、以下の式を考えてみます。

 SET match = value?.N

この式は、目的のオペランドがゼロもしくは 1 つ以上の数字を含み、その他のタイプの文字を含まない場合、True (1) を返します。

交互パターンの指定 (論理 OR)

交互パターンを使用すると、指定した複数のパターン列のいずれかとオペランドが一致するかどうかをテストできます。これにより、パターン・マッチングで論理 OR 機能が得られます。

交互パターンの構文は、以下のとおりです。

( pattern-element sequence {, pattern-element sequence }...)

したがって、以下のパターンは、val に文字 “A” が 1 回出現する、あるいは文字 “B” が 1 回出現する場合に True (1) を返します。

 SET match = value?1(1"A",1"B")

交互パターンは、以下のパターン・マッチング式のように入れ子にできます。

 SET match = value?.(.(1A,1N),1P)

例えば、電話番号の妥当性を検証する場合、少なくとも、電話番号は、3 桁目と 4 桁目の間にハイフン (-) のある 7 桁の番号である必要があります。次に例を示します。

nnn-nnnn

また、電話番号に 3 桁の市外局番がある場合、括弧で囲むか、ハイフンで残りの番号から区別する必要があります。次に例を示します。

(nnn) nnn-nnnn
nnn-nnn-nnnn

以下のパターン・マッチング式は、電話番号の 3 つの有効な形式を示します。

 SET match = phone?3N1"-"4N
 SET match = phone?3N1"-"3N1"-"4N
 SET match = phone?1"("3N1") "3N1"-"4N

交互パターンを使用しない場合には、次の複合ブーリアン式が、あらゆる形式の電話番号の妥当性を確認するために必要となります。

  SET match = 
     (
     (phone?3N1"-"4N) || 
     (phone?3N1"-"3N1"-"4N) || 
     (phone?1"("3N1") "3N1"-"4N)
     )

交互パターンを使用する場合、電話番号の妥当性を検証するために、以下の単一のパターンが必要です。

 SET match = phone?.1(1"("3N1") ",3N1"-")3N1"-"4N

この例の交互パターンでは、電話番号の市外局番部分を、1"("3N1")" または 3N1"-" のいずれかで表現することできます。0 から 1 の交互カウント範囲は、オペランドphone が、0 または 1 のエリア・コードを持てることを示します。

1 より大きい反復カウントを持つ交互パターンは、使用できるパターンの組み合わせを多く生成できます。以下の交互パターンは、例で示されている文字列と一致する以外に、26 とおりの 3 文字の文字列と一致します。

 SET match = "CAT"?3(1"C",1"A",1"T")

不完全パターンの使用法

パターン・マッチングにより、文字列の一部しか一致しない場合、False (0) の結果を返します。つまり、パターンがすべて比較された後は、文字列が残っていてはならないことを示します。以下の式は、パターンの最後の “R” が一致しないため、False (0) を返します。

 SET match = "RAW BAR"?.U1P2U

パターンの複数解釈

オペランドを比較する際に、1 つのパターンに複数の解釈が可能な場合があります。例えば、以下の式は 2 とおりの解釈ができます。

 SET match = "/////A#####B$$$$$"?.E1U.E
  1. 最初の “.E” が部分文字列の “/////” と一致し、1U は “A” と一致し、2番目の “.E” は部分文字列の “#####B$$$$$” と一致します。

  2. 最初の “.E” が部分文字列は “/////A#####” と、1U は “B” と一致し、2番目の “.E” は部分文字列の “.E” と一致します。

    少なくとも式の 1 つの解釈が True (1) である場合、式の値は True となります。

非マッチ演算

非マッチ演算は、パターン・マッチング演算子と共に単項否定演算子 ( ' ) を使用して記述できます。

operand'?pattern

非マッチ演算は、パターン・マッチングの真偽値を反転します。オペランドの文字がパターンと一致しない場合、非マッチ演算は True (1) を返します。パターンがオペランドの文字のすべてに一致する場合、非マッチ演算は False (0) を返します。

以下の例では、非マッチ演算が使用されています。

  WRITE !,"abc" ?3L
  WRITE !,"abc" '?3L
  WRITE !,"abc" ?3N
  WRITE !,"abc" '?3N
  WRITE !,"abc" '?3E

パターンの複雑さ

複数の変更と不明確なパターンによるパターン・マッチは、長い文字列に適用される場合、多くのレベルをシステム・スタックに繰り返す場合があります。まれに、この繰り返しが、数千レベルにまで増加し、スタックのオーバーフローおよびプロセスのクラッシュが発生するおそれがあります。このような極端な状況が発生した場合、Caché は、現在のプロセスのクラッシュの危険を冒すよりはむしろ、<COMPLEX PATTERN> エラーを発行します。

このようなエラーが発生した異常時には、パターンを簡素化するか、または元の文字列のより短いサブユニットにパターンを適用することをお勧めします。

パターンの実行を中断するには Crtl-C キーコマンドを発行します。なお、これによって <INTERRUPT> エラーが発生します。

間接演算

ObjectScript の間接演算子 (@) は、変数に間接的に値を割り当てることができます。間接演算とは、コマンド行、コマンド、コマンド引数の一部あるいはすべてを、データ・フィールドの内容で、実行時にダイナミックに置換する手段です。Caché は、関連するコマンドを実行する前に、置換を実行します。

間接演算は、他の方法より能率的かつ汎用的にコーディングできますが、必ずしも使用する必要はありません。XECUTE コマンドなど他の方法を使用して、間接演算と同様の機能を常に実行できます。

間接演算は、明らかに便利な場合にのみ使用します。間接演算は、Caché がコンパイル・フェーズの間ではなく、実行時に必要な評価を実行するため、性能に影響を与えます。また、複雑な間接演算を使用する場合、明確なコードを記述する必要があります。間接演算は、コード解析を複雑にする場合があるからです。

間接演算は、添え字間接演算の場合を除いて、間接演算子 (@) で指定され、以下の形式になります。

@variable

variable は、置換する値を取得する変数を識別します。置換する値で参照されるすべての変数は、プロシージャで使用されているとしてもパブリック変数です。変数は配列ノードにできます。

以下のルーチンは、間接演算がその右側にある変数全体の値を参照することを示します。

IndirectionExample
 SET x = "ProcA"
 SET x(3) = "ProcB"
 ; The next line will do ProcB, NOT ProcA(3)
 DO @x(3)
 QUIT
ProcA(var)
 WRITE !,"At ProcA"
 QUIT
ProcB(var)
 WRITE !,"At ProcB"
 QUIT

Caché には、以下の 5 つの間接演算があります。

  • 名前間接演算

  • パターン間接演算

  • 引数間接演算

  • 添え字間接演算

  • $TEXT 引数間接指定

@変数が発生するコンテキストによって、実行する間接演算が異なります。各間接演算の説明を以下に示します。

間接演算は、ドット構文には使用できません。ドット構文が実行時ではなく、コンパイル時に構文解析されるためです。

名前間接演算

名前間接演算では、間接演算は、変数名、行ラベル、ルーチン名として評価されます。Caché は、変数の内容をコマンド実行前に要求された名前に置換します。

名前間接演算は、パブリック変数にのみアクセスできます。詳細は、このドキュメントの "ユーザ定義コード" の章を参照してください。

名前付き変数を参照するために間接演算を使用する場合、間接演算の値は、必要な添え字すべてを含め、完全なグローバル変数名またはローカル変数名にする必要があります。以下の例では、Caché は変数 B に 6 を設定します。

 SET Y = "B",@Y = 6
Important:

呼び出しが間接演算を使用して、オブジェクト・プロパティの値を取得または設定しようとした場合、エラーが発生する可能性があります。この種の呼び出しは、プロパティのアクセサ・メソッド (<PropertyName>Get<PropertyName>Set) をバイパスしようとするので、使用しないでください。代わりに、このような用途を目的としている $CLASSMETHOD$METHOD、および $PROPERTY の各関数を使用します。詳細は、"Caché オブジェクトの使用法" の “ObjectScript でのオブジェクトの使用法” の章にある “オブジェクトへの動的アクセス” のセクションを参照してください。

行ラベルを参照するために間接演算を使用する場合、間接演算の値は、構文的に有効な行ラベルにする必要があります。以下の例では、Caché は D を以下のように設定します。

  • N が 1 の場合、行ラベルの値は FIG

  • N が 2 の場合、行ラベルの値は GO

  • その他の場合の値は STOP

その後、Caché は D に与えられた値のラベルに制御を渡します。

B SET D = $SELECT(N = 1:"FIG",N = 2:"GO",1:"STOP")
 ; ...
LV GOTO @D

ルーチン名を参照するために間接演算を使用する場合、間接演算の値は、構文的に有効なルーチン名である必要があります。以下の例では、名前間接演算を DO コマンドで使用し、適切なプロシージャ名を渡します。実行時、変数 loc の内容が、要求されている名前に置換されます。

Start
 READ !,"Enter choice (1, 2, or 3): ",num
 SET loc = "Choice"_num 
 DO @loc
 RETURN
Choice1()
 ; ...
Choice2()
 ; ...
Choice3()
 ; ...

名前間接演算は、名前の値のみを置換できます。以下の例で、2 番目の SET コマンドは、コンテキストに起因するエラー・メッセージを返します。等号の右側の式を評価する際、Caché は @var1 を数値ではなく、変数名に対する間接参照と解釈します。

 SET var1 = "5"
 SET x = @var1*6

正確に実行するには、上記の例を以下のように修正します。

 SET var1 = "var2",var2 = 5
 SET x = @var1*6

パターン間接演算

パターン間接演算は、特殊な形式の間接演算です。間接演算子はパターン・マッチを置換します。間接演算の値は、有効なパターンの必要があります。(パターン・マッチに関しては、"パターン・マッチング" で説明されています)。パターン間接演算は、可能性のあるパターンを複数選択し、それらを単一のパターンとして使用する場合に特に役立ちます。

以下の例では、間接演算をパターン・マッチングに使用し、郵便番号 (ZIP) が有効かどうかを判断します。コードは、5 桁 (nnnnn) あるいは 9 桁 (nnnnnnnnn) のいずれかです。

最初の SET コマンドは、5 桁の形式に対するパターンを設定します。次の SET コマンドは、9 桁の形式に対するパターンを設定します。この 2 番目の SET コマンドは、後置条件式 ($LENGTH(zip) = 10) が True (0 以外) の場合に実行されます。この条件は、ユーザが 9 桁を入力した場合にのみ発生します。

GetZip()
 SET pat = "5N"
 READ !,"Enter your ZIP code (5 or 9 digits): ",zip
 SET:($LENGTH(zip)=10) pat = "5N1""-""4N"
 IF zip'?@pat { 
   WRITE !,"Invalid ZIP code"
   DO GetZip()
 }

パターン・マッチングに間接演算を使用すると、アプリケーション中で使用するパターンをローカライズするのに便利です。この場合、パターンをそれぞれ別々の変数に格納しておき、実際のパターン・テストでは間接演算でそれらを参照できます (これは、名前間接演算の例でもあります)。このようなアプリケーションを移植するには、パターン変数自体を変更するだけで済みます。

引数間接演算

引数間接演算では、間接演算の結果は、1 つ以上のコマンド引数として評価されます。一方、名前間接演算は、引数の一部のみを適用します。

この違いを理解するには、以下の例と "名前間接演算" の例を比較してください。

Start
 SET rout = "^Test1"
 READ !,"Enter choice (1, 2, or 3): ",num
 SET loc = "Choice"_num_rout 
 DO @loc
 QUIT

この場合の引数間接演算の例は、@loc が引数を完全な形式 (すなわち、label^routine) で提供します。名前間接演算の例では、@loc は引数の一部分のみ提供するため、@loc が名前間接演算の例となります (エントリ・ポイントが、別のルーチンではなく、現在のルーチンに存在する label 名)。

以下の 2 番目の SET コマンドは、名前間接演算 (変数名である引数の一部のみに適用) の例であり、一方、3 番目の SET コマンドは、引数間接演算 (引数全体に適用) の例です。

 SET a = "var1",b = "var2 = 3*4"
 SET @a = 5*6
 SET @b
 WRITE "a = ",a,!
 WRITE "b = ",b,!

添え字間接演算

添え字間接演算は、名前間接演算の拡張形式です。添え字間接演算では、間接演算の値はローカルあるいはグローバルの配列ノード名である必要があります。また、他の間接演算とは構文的に異なります。添え字間接演算は、以下の 2 つの間接演算子を使用します。

 @array@(subscript) 

^client というグローバル配列で、最初のレベルのノードにはクライアント名、2 番目にはクライアントの番地、3 番目にはクライアントの市区町村、都道府県、郵便番号が含まれていると想定します。この配列の最初のレコードにあるこれら 3 つのノードを出力するには、以下の形式で WRITE コマンドを使用します。

 WRITE !,^client(1),!,^client(1,1),!,^client(1,1,1)

実行すると、このコマンドは以下のように出力する場合があります。

John Jones
42 Arnold St.
Boston, MA 02745

レコードの範囲を出力するには (例えば、先頭から 10 件のレコード)、WRITE コマンドが FOR ループの中で実行されるようにコードを変更します。以下はその例です。

 FOR i = 1:1:10 {
 WRITE !,^client(i),!,^client(i,1),!,^client(i,1,1)
 }

FOR ループを実行するたびに変数 i は 1 ずつ増加し、その変数を使用して、出力する次のレコードを選択します。

この例は、前述の例よりも一般的ですが、配列名と出力レコード数の両方を明示的に指定する点で特殊です。

以下のように添え字間接演算を使用して、このコードをさらに一般的な形に変更し、ユーザが、3 つのノード・レベルに名前、町名、および都市情報を格納している任意の配列 (グローバルまたはローカル) から、一定範囲のレコードをリストできるようにします。

Start
 READ !,"Output Name, Street, and City info.",!
 READ !,"Name of array to access: ",name
 READ !,"Global or local (G or L): ",gl
 READ !,"Start with record number: ",start
 READ !,"End with record number: ",end
 IF (gl["L")!(gl["l") {SET array = name}
 ELSEIF (gl["G")!(gl["g") {SET array = "^"_name}
 SET x = 1,y = 1
 FOR i = start:1:end {DO Output}
 RETURN
Output()
 WRITE !,@array@(i)
 WRITE !,@array@(i,x)
 WRITE !,@array@(i,x,y)
 QUIT

Output サブルーチンにある WRITE コマンドは、添え字間接演算を使用して、要求されている配列とレコード範囲を参照します。

添え字間接演算の評価で、間接演算のインスタンスが、添え字のないグローバルまたはローカルの変数を参照する場合、間接演算の値は、変数名、および括弧を含む 2 番目の間接演算子の右側にあるすべての文字になります。

ローカル変数の添え字レベルの最大数は 255 です。添え字間接演算は、多次元オブジェクト・プロパティに 254 個を超える添え字を参照できません。グローバル変数の添え字レベルの最大数は添え字に応じて異なり、レベルが 255 を超える場合もあります。これは、"Caché グローバルの使用法" の "グローバル構造" で説明しています。間接演算を使用して 255 より大きな添え字レベルをローカル変数に移入しようとすると、<SYNTAX> エラーが返されます。

クラス・パラメータは、ローカル変数またはグローバル変数をベースとして使用するのと同様の方法で、添え字間接演算のベースとして使用できます。例えば、以下の構文でクラス・パラメータを使用して、添え字間接演算を実行できます。

  SET @..#myparam@(x,y) = "stringval"

$TEXT 引数間接指定

名前からわかるように、$TEXT 引数間接演算は、$TEXT 関数の引数のコンテキストでのみ使用可能です。この間接演算の値は、有効な $TEXT 引数とする必要があります。

$TEXT 引数間接演算を使用する主な目的は、同じ結果を返す間接演算を複数の形式で記述しなくてもすむようにすることにあります。例えば、ローカル変数 LINE に "START^MENU" のエントリ参照が含まれている場合、行ラベルとルーチン名に対し名前間接演算を使用して、行テキストを取得できます。以下がその例です。

 SET LINETEXT = $TEXT(@$PIECE(LINE,"^",1)^@$PIECE(LINE,"^",2))

以下のように $TEXT 引数間接演算を使用すると、より単純な方法で同じ結果を返すことができます。

 SET LINETEXT = $TEXT(@LINE)
FeedbackOpens in a new tab