値の設定ブロック

値の設定ブロックとは、プロパティー、フィールド、または変数の値を設定できるコード内の領域のことです。 プロパティーの背景については、『EGL プロパティーの概要』を参照してください。

以下のアクションのいずれかを実行する場合は、値の設定ブロックを含めることができます。

最後の 2 つの事例では、フィールドにのみ、値を代入できます。

通常、プログラマーは、パーツ・コンテンツの冒頭に値の設定ブロックを 1 つ配置します。しかし、プロパティーや代入する値ごとに別々の値の設定ブロックを使用することも、 有効範囲の規則に違反しない範囲でパーツ全体に分散させることもできます (有効範囲を参照してください)。 例えば、次のコード内の値の設定ブロックは、handleHardIOErrors プログラム・プロパティーをオンにします。
program hello
	myString STRING = "Hello, Cleveland";
	{handleHardIOErrors = YES}   // これが実行されます
	...
end
セミコロンを移動すると、このプログラムは検証エラーを出します。
program hello
	myString STRING = "Hello, Cleveland"
	{handleHardIOErrors = YES};   // これは myString 宣言の一部です
	...
end

問題は、handleHardIOErrors が、「Hello, Cleveland.」というストリングの有効範囲内に入ったことにあります。 ストリングに設定すべきフィールドはありません (handleHardIOErrors というフィールドは論外です)。 そのため、EGL は式を解決できません。

値の設定ブロックには以下のような効果があります。 次の文は、初期値が NULL 以外 (この場合は 0) の NULL 可能変数を作成します。
myInt INT?{};
次の例の結果は、NULL 値例外になります。
myList Dictionary;   // myList = null
myList.x = 23;       // イリーガルな参照
ただし、次のコードでは、 代入が試行される前に、新規の辞書変数が初期化されます。
myList2 Dictionary;   // myList2 = null
myList2{ x = 23 };    // myList2 には 1 つのキー x があり、その値は 23 です
値の設定ブロックを使用して構造化レコード変数内の値を初期化できます。 以下の例を考えてください。
package com.companyb.customer;

Record StructuredRecordA
10 fullCheckNum NUM(25);
  15 bankNum NUM(9);
  15 acctNum NUM(10);
  15 checkNum NUM(6);
end

program calculate type BasicProgram

  function main()
    myRec1 StructuredRecordA 
      {fullCheckNum = 9531008501602141091001484};
    writeStdOut(myRec1.bankNum);  // 953100850
    writeStdErr(myRec1.checkNum); // 1484
  end
end
トップレベル・フィールドを設定すると、サブストラクチャー・フィールドも設定されます。また、以下の例のようにサブストラクチャー・フィールドを個別に設定することもできます。
  myRec2 StructuredRecordA {checkNum = 1485};
  writeStdOut(myRec2.fullCheckNum); // 1485

値の設定ブロックで同一フィールドまたはプロパティーに複数の割り当てを 行うと、最後の割り当てが有効になります。この規則は、このトピック内の『複合プロパティーでの値の設定ブロック』で説明されている複合プロパティーのフィールドにも適用されます。

基本的な状態での値の設定ブロック

次の規則は、基本的な事例のほとんどに適用されます。
  • 各値の設定ブロックは、左中括弧 ({) で始まり、コンマで区切ったゼロ以上のエントリーを含んでおり、 右中括弧 (}) で終わります。
  • 各エントリーは、次の 2 つの書式のいずれかをとります。
    • inputRequired = yes のような、名前と値のペア。
    • 一連の定位置値 (配列の連続する要素に割り当てられる連続する値)。

いずれの場合でも、値の設定ブロックは、変更対象のパーツ、変数、またはフィールドの有効範囲内にあります。 分かりやすいように、さまざまな構文の例を以下に示します。

最初の例では、2 つのプロパティー (inputRequiredalign) を持つプリミティブ型変数を示します。
   // 有効範囲は myVariable です。
   myVariable INT
   {
      inputRequired = yes,
      align = left
   };
次の例は DataItem パーツ定義を示しています。
  // 有効範囲は optionEntry です。
  DataItem optionEntry INT
  {
      inputRequired = yes,
      align = left
  };
  end
次の例は、直前のパーツを型として使用し、プロパティーのいずれかをオーバーライドする変数宣言を示しています。
  // 有効範囲は menu1Option です。
  menu1Option optionEntry
  {
      inputRequired = no
   };
最初の 2 つの assignment 文は、値の設定ブロックを使用しません。
  myRecord02.myContent01 = "abc";
  myRecord02.myContent02 = "xyz";
次の簡略化された代入文は、上記の 2 つと同等です。
  myRecord02
  {
      myContent01="abc",
      myContent02="xyz"
   };

この簡略化された代入文は、構造化レコード内のフィールドでは使用できません。 また、これを使用してプロパティーを設定することもできません。

レコード内のフィールド用の値の設定ブロック

レコード変数内のフィールドに値を割り当てる場合は、 以下のように有効範囲を特定のフィールドへ絞り込みます。

次のレコード定義を考えてみます。
  record myBasicRecord03 type basicRecord
    myInt04 INT;
  end

  record myBasicRecord02 type basicRecord
    myInt03 INT;
    myRec03 myBasicRecord03;
  end

  record myBasicRecord type basicRecord  
    myInt01 INT;
    myInt02 INT;
    myRec02 myBasicRecord02;
 end
以下のステップを使用して、任意のフィールドにプロパティー値を代入できます。
  • レコードの値の設定ブロックを作成します。
  • 有効範囲を絞り込むために、一連のフィールド名を埋め込みます。
  • フィールド固有の値の設定ブロックを作成します。

プロパティー値を代入する構文には、次の例に示す書式のどれでも使用できます。これらは、フィールド myInt04 に適用されます。

  // ドット構文
  myRecB myBasicRecord 
  { 
    myRec02.myRec03.myInt04{ align = left } 
  };

  // 大括弧構文
  // この構文を使用して、固定構造体内のフィールドに
  // 影響を及ぼすことはできません
  
  myRecC myBasicRecord 
  { 
    myRec02["myRec03"]["myInt04"]{ align = left } 
  };

  // 中括弧構文
  myRecA myBasicRecord 
  { 
    myRec02 {myRec03 { myInt04 { align = left }}}
  };
複雑な事例でも、値の設定ブロック内のエントリーをコンマで区切ります。 所定のブロックがネストされているレベルを考慮する必要があります。
  // ドット構文
  myRecB myBasicRecord 
  { 
    myInt01 = 4,
    myInt02 = 5,
    myRec02.myRec03.myInt04{ align = left }, 
    myRec02.myInt03 = 6
  };

  // 大括弧構文
  myRecC myBasicRecord 
  { 
    myInt01 = 4,
    myInt02 = 5,
    myRec02["myRec03"]["myInt04"]{ align = left }, 
    myRec02["myInt03"] = 6
  };

  // 中括弧構文。
  // ただし、これを使用すると保守がずっと難しくなります。
  myRecA myBasicRecord 
  { 
    myInt01 = 4,
    myInt02 = 5,
    myRec02 
      {
        myRec03 
          { myInt04 
            { action = label5 }},
        myInt03 = 6
      }
  };

値の設定ブロック内での「this」の使用

変数宣言または assignment 文の中で、レコード・プロパティーと同じ名前が付いたフィールド (keyItems など) を含んでいるコンテナー (SQL レコードなど) を使用できます。 プロパティーではなくフィールドを参照するには、キーワード this を使用します。 これにより、値の設定ブロックが存在する宣言として有効範囲が設定されます。

次のレコード定義を考えてみます。
  Record ExampleRecord type SQLRecord
    { tableNames = [["myTable"]],
      keyItems = [myKey] }
    myKey CHAR(10);
    myOtherKey CHAR(10);
    keyItems CHAR(60);
  end 
次のレコード宣言は、最初にプロパティー keyItems の値を設定し、次に同名のフィールドの値を設定します。
  myRecord ExampleRecord 
  { 
     keyItems = [myOtherKey],
     this.keyItems = "abc"
  };

配列宣言の例については、『値の設定ブロックの追加サンプル』を参照してください。

複合プロパティーでの値の設定ブロック

EGL には、従来から、名前が @ 記号で始まる複合プロパティー が多数含まれています。 複合プロパティーは独自のプロパティー (プロパティー・フィールドと呼ばれる) を持ち、 従属する値の設定ブロックで値が割り当てられます。 以下に、サービス変数宣言で使用される @xml 複合プロパティーの例を示します。
  myService ExampleServicePart 
  { @xml
    {name="myService",
     namespace="http://www.customerpackage.companyb.commy.useful.service"}
  };

値の設定ブロックの追加サンプル

この例では以下のレコード定義を使用します。
  Record Point
    x INT;
    y INT;
  end

  Record Rectangle
    topLeft Point;
    bottomRight Point;
  end
次のコードは有効です。
  Function test()
    screen Rectangle
    {
      topLeft{x=1, y=1},
      bottomRight{x=80, y=24}
    };
  
    // 次のコードと等価の文を使用して、
    // コード内の x、y を変更します。
    
    //   screen.topLeft.x = 1;
    //   screen.topLeft.y = 2;
    screen.topLeft{x=1, y=2};
  end
次に、Point 要素の動的配列を同じ関数内で初期化します。
  pts Point[2]
  {
    this[1]{x=1, y=2},
    this[2]{x=2, y=3}
  };
この時点で配列に入っている各要素の値を設定した後、次のように最初の要素を別の値に設定します。
  pts{ x=1, y=1 };
  pts[1]{x=10, y=20};

キーワード this は、値の設定ブロック外では別の意味を持つことに注意してください (「this」キーワードを参照)。 いずれの場合でも、ここに pts[1] を使用することは未確定ではないので、区別は不要です。

次に、Point 型の別の動的配列を考えてみます。
  points Point[];
以下の 2 つの割り当てでは、配列が初期化されていないので NullValueExceptions がスローされます。 配列は、参照型であるため、初期値は NULL です (参照変数を参照)。
  points{x=1, y=1};
  points[1]{x=10, y=20};
配列を初期化すると、この配列に要素を追加し、さらに単一の文を使用してすべての要素に値を設定できます。
  points{};
  points.resize(2);
  points{x=1, y=1};

フィードバック