Q:  Is it more efficient to use one multi-dimensional array or
    several single dimension arrays in a program. The array(s)
    would be static and called at the top of the program.

A:  [Don Caton]

    Clipper does not have multi-dimensional arrays. If you're
    thinking about something like aArray[1][2], that is NOT a
    multi-dim array, the first element of 'aArray' just contains
    another array.  This is sometimes referred to as "nested"
    or "ragged" arrays.  Array elements in Clipper can contain
    other arrays, but arrays can never have more than one
    dimension.

    This is not just a semantical difference, this is critically
    important to understanding Clipper arrays.  Given:

         aArray1    := { 1, 2, NIL }
         aArray2    := { 3, 4 }
         aArray1[3] := aArray2

    you can access the first element of aArray2 via 'aArray1[3][1]'
    or 'aArray2[1]'; both expressions will retrieve the same data.
    Likewise, assigning a new value into either expression will affect
    the other, since they are looking at the same piece of data.
    
    If you're familiar with C, you might think of 'aArray1' and
    'aArray2' as containing pointers to their respective arrays,
    and 'aArray1[3]' and 'aArray2' both contain the same pointer.

    In terms of performance, it is definitely faster to access that
    piece of data as 'aArray2[1]' rather than 'aArray1[3][1]'.  The
    first way only requires a single lookup as the reference
    'aArray2' points to the desired array.  The second way requires
    'aArray1' to be located, then the data in the 3rd element is
    obtained which is the reference to 'aArray2'.  In other words,
    the second method requires an additional indirection before the
    desired data can be located.

    The further "down" the desired array element is from the base
    reference, the more indirections (and overhead) are required
    to retrieve it.  Something like aArray[1][3][5][6] would
    require 3 array retrievals before obtaining the reference to
    the array containing the 6th element you want.  In general, this
    isn't something to be overly concerned with but don't go making
    your arrays unnecessarialy complex.  If you had an array such as
    the one above and you needed access to many of the elements in
    the last array, you should do something like:

         aTemp := aArray[1][3][5]
         xElement := aTemp[6]
         xElement := aTemp[7]
         ... etc.

    This retrieves the array reference in aArray[1][3][5] into a
    temporary variable, and eliminates the need for Clipper to
    repeatedly start out at aArray1 and retrieve all the
    intermediate array references.

    As far as an array being STATIC, that has no bearing on
    efficiency of accessing arrays, or any other data type
    for that matter.  STATIC is a visibility and lifetime issue.
    Accessing STATIC (or LOCAL) data will be a bit more efficient
    than something with a storage class of PUBLIC or PRIVATE, but
    that's due to symbol table indirection and has nothing to do
    with array access in particular.

Q:  So which approach is faster:

         aArray[1][5][3][6] := nVal1
         aArray[1][5][3][7] := nVal2
         aArray[1][5][3][8] := nVal3

    or

         aTemp    := aArray[1][5][3]
         aTemp[6] := nVal1
         aTemp[7] := nVal2
         aTemp[8] := nVal3

A:  [Don Caton]

    The second method is always going to be faster, for the simple
    reason that arrays in Clipper are strictly single-dimensional.
    When you access something like 'aArray[1][5][3][6]', internally
    Clipper has to access 4 discrete arrays from the object memory
    system in order to return the desired element.

    The first array is the one referred to by 'aArray'.  When that is
    accessed, the first element is retrieved which also contains an
    array reference.  That array is accessed and its fifth element
    is retrieved which again contains an array reference.  That array
    is accessed and its third element is retrieved which yet again,
    contains an array reference.  Finally, that array is accessed
    and the sixth element is retrieved and assigned into the variable.

    Any or all of those arrays could be in memory, in ems or on disk.
    The worst case would be that all four of those arrays were
    swapped out to disk and each one would have to be brought back in,
    one at a time.

    Just because an array contains references to other arrays,
    they are still completely discrete units of data.  Doing
    something like 'aArray[1][5][3][6]' doesn't access all
    the arrays in one operation, there's simply no way to know
    what any of those elements contain until all the relevant arrays
    and elements are accessed.  Element 3 of the third array might not
    contain an array reference for example, so the expression
    would fail at the fourth internal array access.

    If Clipper's arrays were truly multidimensional they would also be
    symmetrical, and any element in any dimension could be accessed
    simply by calculating the proper offset.  For example, in Foxbase
    the array element 'x(2,2)' is actually the fourth element
    in array 'x'.  In Clipper, the absolute location of an element
    in a multi-subscriped array reference cannot be calculated
    in one shot because the expression doesn't refer to a single data
    entity.

    It's always going to be faster therefore to obtain the reference
    to the "lowest" array you need to access and hold on to that
    if you need to access more than one of its elements.

    For similar reasons, it's always faster to assign an object's
    instance variable to a local variable when you need to access
    it more than once.  That way you eliminate the repeated message
    lookup and array retrieval (objects are really arrays at the
    internal level).


                                  ###