Arrays

EGL supports the following kinds of arrays:

In all cases, the following rules apply:

Arrays of structure items

You declare an array of structure items when you specify that a structure item in a record or form part has an occurs value greater than one, as in the following example:

  Record myRecordPart
    10 mySI CHAR(1)[3];
  end

If a record called myRecord is based on that part, the symbol myRecord.mySi refers to a one-dimensional array of three elements, each a character.

Usage of an array

You can reference an entire array of structure items (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 function sysLib.size. That function returns the occurs value of the structure item.

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

One-dimensional 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 subscript. The subscript is either an integer or an item that resolves to an integer; for example, you can refer to the second element of the example array as myStruct.mySi[2]. The subscript can vary from 1 to the occurs value of the structure item, and a run-time error occurs if the subscript is outside of that range.

If you use the name of a structure-item array in a context that requires an item but do not specify a bracketed subscript, EGL assumes that you are referring to the first element of the array, but only if you are in VisualAge Generator compatibility mode. It is recommended that you identify each element explicitly. If you are not in VisualAge Generator compatibility mode, you are required to identify each element explicitly.

The next examples show how to refer to elements in a one-dimensional array. In those examples, valueOne resolves to 1 and valueTwo resolves to 2:

  // these refer to the first of three elements:
  myRecord.mySi[valueOne]
  myRecord.mySi             // not recommended; and valid
                            // only if VisualAge Generator
                            // compatibility is in effect
  // this refers to the second element:
  myRecord.mySi[valueTwo]

A one-dimensional array may be substructured, as in this example:

  record myRecord01Part
    10 name[3];
      20 firstOne CHAR(20);
      20 midOne CHAR(20);
      20 lastOne CHAR(20);
  end

If a record called myRecord01 is based on the previous part, the symbol 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 may refer to each element in myRecord01.name without reference to the substructure; for example, myRecord01.name[2] refers to the second element. You also may refer to a substructure within an element. If uniqueness rules are satisfied, for example, 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 last two are valid only if the program, page-handler, or library property allowUnqualifiedItemReferences is set to yes.

For details on the different kinds of references, see References to variables and constants.

Multidimensional array

If a structure item with an occurs value greater than one is substructured and if a subordinate structure item also has an occurs value greater than one, the subordinate structure item declares an array with an additional dimension.

Let's consider another record part:

  record myRecord02Part
    10 siTop[3];
      20 siNext CHAR(20)[2];
  end

If a record called myRecord02 is based on that part, each element of the one-dimensional array myRecord02.siTop 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 structure item siNext declares a two-dimensional array, and you can refer to an element of that array by a syntax like this:

  // row 1, column 2
  myRecord02.siTop.siNext[1,2]

To clarify what area of memory is being referenced, let's 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:

  // i, j, myTopOccurs, and myNextOccurs are data items; 
  // myRecord02 is a record; and
  // sysLib.size() returns the occurs value of a structure item.
  i = 1;
  j = 1;
  myTopOccurs = sysLib.size(myRecord02.siTop);
  myNextOccurs = sysLib.size(myRecord02.siTop.siNext);
  while (i <= myTopOccurs)
    while (j <= myNextOccurs)
      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 2-dimensional array.

An example declaration of a 3-dimensional array is as follows:

  record myRecord03Part
    10 siTop[3];
      20 siNext[2];
        30 siLast CHAR(20)[5];
  end

If a record called myRecord03 is based on that part and if uniqueness rules are satisified, you can reference the last element in the array in any of the following ways:

  // each level is shown, and a subscript is on each level
  myRecord03.siTop[3].siNext[2].siLast[5]

  // each level shown, and subscripts are on lower levels
  myRecord03.siTop.siNext[3,2].siLast[5]
  myRecord03.siTop.siNext[3][2].siLast[5]

  // each level is shown, and subscripts are on the lowest level
  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]

  // the container and the last level is shown, with subscripts
  myRecord03.siLast[3,2,5]
  myRecord03.siLast[3,2][5]
  myRecord03.siLast[3][2,5]
  myRecord03.siLast[3][2][5]

  // only the last level is shown, with subscripts
  siLast[3,2,5]
  siLast[3,2][5]
  siLast[3][2,5]
  siLast[3][2][5]

As indicated by the previous example, you reference an element of a multidimensional array by adding a bracketed set of subscripts, in any of various ways. In all cases, the first subscript refers to the first dimension, the second subscript refers to the second dimension, and so forth. Each subscript can vary from 1 to the occurs value of the related structure item, and a run-time error occurs if a subscript resolves to a number outside of that range.

First, consider the situation when subscripts 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 items, with each name separated from the next by a period, as in this example:
      myRecord03.siTop.siNext.siLast

  • You can specify the name of the variable, followed by a period, followed by the name of the lowest-level item of interest, as in this example:
      myRecord03.siLast

  • If the lowest-level item of interest is unique in a given name space, you can specify only that item, as in this example:
      siLast

Next, consider the rules for placing array subscripts:

  • You can specify a subscript 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 subscripts 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 subscripts 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 subscripts than are appropriate at a given level. as in this example:
      // NOT valid
      myRecord03.siTop[3,2,5].siNext.siLast

  • You can isolate a subscript within a bracket or can display a series of subscripts, each separated from the next by a comma; or you can 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]

For another review of the different ways to reference a structure item, see References to variables and constants.

Static arrays of records and data items

You can declare a static array of records or data items by specifying a size value in brackets, as in the following examples:

  myDataItem01 CHAR(30)[5];        // an array of 5 items
  myDataItem02 myDataItemPart[6];  // an array of 6 items
  myRecord myRecordPart[7];        // an array of 7 records

The size value must be an integer literal.

A static array may be used locally within a given function, may be a program-global variable, and may even be declared in a library and used by many programs, libraries, and/or page handlers. The array cannot be passed as an argument to another function (although individual elements can be passed). Also, the array cannot act as a parameter.

The number of dimensions in a static array of records is the highest number of array dimensions in the record structure, plus one dimension for the record array itself. Assume, for example, that your code can access the following part at development time:

  record myRecordPart
    siTop[3];
      siNext CHAR(10)[2];
  end

The following statement declares an array of three dimensions:

  myRecord myRecordPart[5];

In the previous example, these references are valid:

  myRecord.siTop.siNext[1,1,2]
  siNext[1,1,2]

The in-memory arrangement of elements of the static array are as described for structure-item arrays.

The system variable sysLib.size(arrayName) contains the number of elements in the first dimension of a static array of records or data items. (Substitute the array name for arrayName and note that the name may be qualified by a package name, a library name, or both.)

Dynamic arrays of records and data items

You can declare an array of records or data items without specifying the number of elements, and in this case the number varies at run time as your code invokes system functions that append, insert, or delete elements or that remove the array. This dynamic array is useful for a variety of tasks but is not available in forms.

The syntax for declaring a dynamic array includes brackets with no size value, as in the following examples:

  // an array of 5 items or less
  myDataItem01 CHAR(30)[] { maxSize=5 };

  // an array of 6 items or less
  myDataItem02 myDataItemPart[] { maxSize=6 };

  // an array of the maximum number of items 
  // (the maximum depends on the generated language)
  myRecord myRecordPart[];

The rules for referencing the elements of a dynamic array are equivalent to the rules for referencing a static array. If your code refers to a dynamic array of records or data items and does not specify brackets or a subscript, the reference is to the array as a whole.

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

Functions and variables for processing dynamic arrays

A set of functions and read-only variables are available for each dynamic array. In the following descriptions, substitute the array name for arrayName and note that the name may be qualified by a package name, a library name, or both:

arrayName.appendAll(appendArray)

This function does as follows:

  • Appends to the array that is referenced by arrayName, adding a copy of the array that is referenced by appendArray

  • Increments the array size by the number of added elements

  • Assigns an appropriate index value to each of the appended elements

The elements of appendArray must be of the same type as the elements of arrayName.

arrayName.appendElement(content)

This function places an element to the end of the specified array and increments the size by one. For content, you can substitute a variable of the appropriate type; alternatively, you can specify a literal that is assigned to an element created during the operation. The process copies data; if you assign a variable, that variable is still available for comparison or other purposes.

The rules for assigning a literal are as specified in Assignments.

arrayName.insertElement(content, index)

This function does as follows:

  • Places an element in front of the element that is now at the specified location in the array

  • Increments the array size by one

  • Increments the index of each element that resides after the inserted element

content is the new content (a constant or variable of the appropriate type for the array), and index is an integer literal or a numeric variable that indicates the location of the new element.

If index is one greater than the number of elements in the array, the function creates a new element at the end of the array and increments the array size by one.

arrayName.removeAll()

This function removes the elements of the array from memory. The array can be used, but its size is zero.

arrayName.removeElement(index)

This function removes the element at the specified location, decrements the array size by one, and decrements the index of each element that resides after the removed element.

index is an integer literal or a numeric variable that indicates the location of the element to be removed.

sysLib.maximumSize

As described in sysLib.maximumSize.

sysLib.size

As described in sysLib.size.

Use of dynamic arrays as arguments and parameters

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; and for a data item, the type must include the same length and decimal places, if any.

A dynamic array cannot be passed as an argument to another program.

An example of a function that uses a dynamic array as a parameter is as follows:

  Function getAll (employees Employee[])
   ;
  end

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

SQL processing and dynamic arrays

EGL lets you use a dynamic array to access rows of a relational database. For details on reading multiple rows, see get. For details on adding multiple rows, see add.

Related concepts
Compatibility with VisualAge Generator
References to variables and constants

Related reference
add
Assignments
EGL system limits
get
in operator
sysLib.size