Arrays

The rules for an EGL array depend on the type of the array.
EGL supports the following kinds of arrays:

In all cases, the maximum number of supported dimensions is seven.

In EGL, the first element in an array has the index 1; in many languages, the first element has the index 0.

Array literals

An array literal consists of a pair of brackets that contains a comma-separated list of literals (including other array literals) or expressions (including array variables). Each array literal has a type, and can be used anywhere an array of the given type is allowed, for instance, as an initializer for an array variable. The following table provides examples of array literals:

Table 1. Array literals
Array literal Type
[ 1, 2, 3 ] SMALLINT[]
[ "hi", "Mom" ] STRING[]
[ new myRecord, new myRecord ] myRecord[]
[ (myPay < 0), (myPay > 0) ] BOOLEAN[]
[ [ 1, 2 ], [ 3, 4 ] ] SMALLINT[][]
[ 3, "cow", [ 4.5, 6.7 ] ] ANY[]

If the types of the elements in the array literal differ, the inferred type of the array is ANY. The elements in the array do not need to be assignment compatible with each other.

Dynamic arrays

You can declare a dynamic array of variables based on any data part except the DataTable:
  • primitives
  • DataItems
  • Records (any type)
  • Delegates
The array itself has an identity independent of its elements:
  • You can call a set of functions using the array name (with the syntax arrayName.functionName() ), to increase or reduce the number of elements at run time. See "Dynamic array functions."
  • The maxSize array-specific property indicates the maximum number of elements that are valid in the array. The default value is unbounded; the number of elements is limited only by the requirements of the target environment. In multidimensional arrays, this refers to the first dimension only.
You do not need to specify a number of elements in your declaration, but if you do, that number indicates the initial number of elements. In the case of multidimensional arrays, enclose each index in separate brackets:
multiDimensionArray INT[2][3];

The syntax for declaring a dynamic array is shown in the following examples:

  // An array of 5 elements or less
  myNames CHAR(30)[] { maxSize=5 };

  // An array of 6 elements or less, 
  // with 4 elements initially
  myDataItemArray myDataItem[4] { maxSize=6 };

  // An array that has no elements 
  // but whose maximum size is the largest possible
  myRecordArray ExampleRecord[];

  // A 3-element array whose elements 
  // are assigned the values 1, 3, and 5
  position int[] = [1,3,5]; 

You can use a literal integer to initialize the number of elements, but neither a variable nor a constant is valid.

Like any other reference variable (see "Reference variables"), you cannot use an array variable until you initialize it.
myIntArray INT[];
myIntArray[2] = 13; // causes NullValueException

myIntArray2 INT[3]
myIntArray2[2] = 13; // this is legal
When you declare an array of arrays, an initial number of elements is valid in the leftmost-specified dimension and in each subsequent dimension until a dimension lacks an initial number. The following declarations are valid:
  // Valid, with maxsize giving the maximum 
  // for the first dimension
  myIntArray01 INT[3][];
  myIntArray02 INT[4][2][] {maxsize = 12};
  myIntArray03 INT[7][3][1];

  // In the next example, array constants indicate 
  // that the outer array initially has 3 elements.
  // The first element of the outer array is 
  // an array of two elements (with values 1 and 2).
  // The second element of the outer array is
  // an array of three elements (with values 3, 4,5).
  // The third element of the outer array is 
  // an array of two elements (with values 6 and 7).
  myIntArray04 INT[][] = [[1,2],[3,4,5],[6,7]];
In the following example, the syntax is not valid because (for instance) the myInt04 array is declared as an array of no elements, but each of those elements is assigned 3 elements:
  // NOT valid
  myInt04 INT[][3];
  myInt05 INT[5][][2];
When your code references an array or an array element, these rules apply:
  • An index can be any numeric expression that resolves to an integer, and can include a function invocation.
  • If your code refers to a dynamic array but does not specify an index or indices, the reference is to the array as a whole.

An out-of-memory situation is treated as a catastrophic error and ends the program.

You can use a set-value block to initialize an array, as in the following examples:
myArray1 int[3] {1,2,3};  // array of 3 elements; values are 1, 2, and 3

This is more efficient than equating the new array to an array literal of [1,2,3]. In the case of the array literal, EGL creates the literal array before assigning the value to myArray1. By using a set-value block, only myArray1 is created.

However, the following will not work because you are trying to assign values to a null array (no initial number of elements specified):
myArray2 int[] {1,2,3}; // throws IndexOutOfBoundsException
If for some reason you need to create an array without specifying an initial number of elements, but the array cannot be null (you want to add elements later), you can use the following syntax:
myArray3 int[] {};  // zero-length, non-null array

Use of dynamic arrays as parameters and arguments

A dynamic array can be passed as an argument to an EGL function. The related parameter must be defined as a dynamic array of the same type as the argument; elements must have the same length and decimal places, if any, in both argument and parameter.

An array passed to a program or function cannot specify the number of elements.

The following example shows a function that uses a dynamic array as a parameter:
  Function getAll (CustomerRecord myCustomers[])
   ;
  end

At run time, the maximum size for a parameter is the maximum size declared for the corresponding argument. The invoked function can change the size of the array, and the change is in effect in the invoking code.

Structure field arrays

You declare a structure field array when you specify that a field in a structured record has multiple occurrences, as in the following example:
  Record ExampleStructuredRecord
    10 mySi CHAR(1)[3];
  end

If a structured record variable named myRecord is based on that definition, the name myRecord.mySi refers to a one-dimensional array of three elements, each a character.

Usage of a structure field array

You can reference an entire array of structure fields (for example, myRecord.mySi) in these contexts:
  • As the second operand used by an in operator. The operator tests whether a given value is contained in the array.
  • As the parameter in the sysLib.size() function. That function returns the number of elements in the array.

An array element that is not itself an array is a field like any other, and you can reference that field in various ways; for example, in an assignment statement or as an argument when you call a function.

An element index can be any numeric expression that resolves to an integer, but the expression cannot include a function invocation.

One-dimensional structure field array

You can refer to an element of a one-dimensional array like myRecord.mySi by using the name of the array followed by a bracketed index number. For example, you can refer to the second element of the example array as myStruct.mySi[2]. The index can vary from 1 to the number of elements in the array, and a runtime error occurs if the index is outside of that range.

You cannot use the name of a structure field array in a context that requires a single value unless you specify an index (for possible exceptions, see "Compatibility" in this topic ).

A one-dimensional array can be substructured, as in this example:
  Record Record01
    10 name[3];
      20 firstOne CHAR(20);
      20 midOne CHAR(20);
      20 lastOne CHAR(20);
  end

If a record named myRecord01 is based on the previous Record definition, the name myRecord01.name refers to a one-dimensional array of three elements, each of which has 60 characters, and the length of myRecord01 is 180.

You can refer to each element in myRecord01.name without reference to the substructure; for example, myRecord01.name[2] refers to the second element. You can also refer to a substructure within an element. For example, if uniqueness rules are satisfied, you can reference the last 20 characters of the second element in any of the following ways:

  myRecord01.name.lastOne[2]
  myRecord01.lastOne[2]	
  lastOne[2]

The final example is valid only if the allowUnqualifiedItemReferences property is set to YES.

For more information about the different kinds of references, see "Reference variables in EGL."

Multidimensional structure field array

If a structure field with multiple elements is substructured and if a subordinate structure field also has multiple elements, the subordinate structure field declares an array with an additional dimension (see "Compatibility").

Consider another Record part:
  Record Record02
    10 siTop[3];
      20 siNext CHAR(20)[2];
  end
If a record variable named myRecord02 is based on that part, each element of the myRecord02.siTop one-dimensional array is itself a one-dimensional array. For example, you can refer to the second of the three subordinate one-dimensional arrays as myRecord02.siTop[2]. The siNext structure field declares a two-dimensional array, and you can refer to an element of that array by either of these syntaxes:
  // row 1, column 2.
  // the next syntax is strongly recommended
  // because it works with dynamic arrays as well
  myRecord02.siTop[1].siNext[2]

  // the next syntax is supported
  // but not recommended
  myRecord02.siTop.siNext[1,2]

To clarify what area of memory is being referenced, consider how data in a multidimensional array is stored. In the current example, myRecord02 constitutes 120 bytes. The referenced area is divided into a one-dimensional array of three elements, each 40 bytes:

  siTop[1]     siTop[2]     siTop[3]

Each element of the one-dimensional array is further subdivided into an array of two elements, each 20 bytes, in the same area of memory:

  siNext[1,1] siNext[1,2] siNext[2,1] siNext[2,2] siNext[3,1] siNext[3,2]
A two-dimensional array is stored in row-major order. One implication is that if you initialize an array in a double while loop, you get better performance by processing the columns in one row before processing the columns in a second. The following example illustrates this idea:
  // i, j, myTopIndex, and myNextIndex are variables; 
  // myRecord02 is a record; and
  // sysLib.size() returns the number of elements in a structure field.
  i = 1;
  j = 1;
  myTopIndex = sysLib.size(myRecord02.siTop);
  myNextIndex = sysLib.size(myRecord02.siTop.siNext);
  while (i <= myTopIndex)
    while (j <= myNextIndex)
      myRecord02.siTop.siNext[i,j] = "abc";
      j = j + 1;
    end
    i = i + 1;
  end

You must specify a value for each dimension of a multidimensional array. The reference myRecord02.siTop.siNext[1], for example, is not valid for a two-dimensional array.

An example declaration of a three-dimensional array is as follows:
  Record Record03
    10 siTop[3];
      20 siNext[2];
        30 siLast CHAR(20)[5];
  end
To understand how to include array indices, consider the situation when indices are not involved:
  • You can specify a list that begins with the name of the variable and continues with the names of increasingly subordinate structure fields, with each name separated from the next by a period, as in this example:
      myRecord03.siTop.siNext.siLast
  • If the lowest-level field name is unique within the variable, you can specify the name of the variable, followed by a period, followed by the name of the lowest-level field, as in this example:
      myRecord03.siLast
  • If the lowest-level field is unique in a given namespace, you can specify only that field, as in this example:
      siLast
Next, consider the rules for placing array indices:
  • You can specify an index at each level where one of several elements is valid, as in this example:
      myRecord03.siTop[3].siNext[2].siLast[5]
  • You can specify a series of indices at any level where one of several elements is valid, as in this example:
      myRecord03.siTop.siNext[3,2].siLast[5]
  • You can specify a series of indices at any level that is at or subordinate to a level where one of several elements is valid, as in this example:
      myRecord03.siTop.siNext.siLast[3,2,5]
  • An error occurs if you assign more indices than are appropriate at a given level. as in this example:
      // NOT valid
      myRecord03.siTop[3,2,5].siNext.siLast
  • You can isolate an index within a bracket, use a series of comma-separated indices, or combine the two usages. The following examples are valid:
      myRecord03.siTop.siNext.siLast[3,2,5]
      myRecord03.siTop.siNext.siLast[3,2][5]
      myRecord03.siTop.siNext.siLast[3][2,5]
      myRecord03.siTop.siNext.siLast[3][2][5]

Compatibility

Table 2. Compatibility considerations for arrays
Platform Issue
COBOL generation Multidimensional arrays are not supported for dynamic arrays.
JavaScript generation The following types are supported: ANY, BIGINT, BIN (but only in the absence of decimal places), Boolean, DataItem, DATE, DECIMAL, Delegate, Dictionary, FLOAT, INT, NUM, NUMBER, SMALLFLOAT, SMALLINT, STRING (but only in the absence of a size limit) , TIME, TIMESTAMP, NUM, MONEY, Service parts, Interface parts, External types (stereotype JavaScript), arrays of supported types, and non-structured Basic, Exception, and SQL Record parts. The following types are not supported: ArrayDictionary, BIN (with decimal places), BLOB, CHAR, CLOB, DBCHAR, HEX, INTERVAL, MBCHAR, NUMC, STRING (with a size limit), PACF, UNICODE, and structured Record parts.
VisualAge® Generator compatibility mode If you use the name of a structure field array without an index in a context that requires a single value, EGL assumes that you are referring to the first element of the array.

Feedback