for i in array_liml(X), array_limh(X) cross
j in array_liml(X[i]), array_limh(X[i])
q := deep_thought(x, i, j)
returns array of q
end for
This sort of thing can be very useful when dealing with ragged arrays. For instance, the situation often develops in the modeling of physical systems that a system array with unchanging boundaries must be evolved and returned with the original boundaries. In the following example, we will use the Sisal operator for array concatenation, "||".
let new_core := evolve(system_array); % new system with no boundaries
top_indx := array_liml(system_array); % positions of top and bottom
btm_indx := array_limh(system_array); % boundaries from old system
new_top := system_array[top_indx]; % actual top boundary
new_btm := system_array[btm_indx]; % actual bottom boundary
left_indx := array_liml(system_array[1]); % positions of left and right
right_indx := array_limh(system_array[1]); % boundaries from old system
% (all rows have same indices)
long_core := for row in core at i % add side boundaries to all rows
left_bound_elt := system_array[ i, left_indx ];
left_bound_array := array [ 1: left_bound_elt ];
right_bound_elt := system_array[ i, right_indx ];
right_bound_array := array [ 1: right_bound_elt ]
returns array of left_bound_array || row || right_bound_array
end for;
long_tall := new_top || long_core || new_btm % add top and bottom
in long_tall % The newly evolved system, complete with boundaries.
end let
This elegant bit of code builds a new system array in three steps. First, function "evolve" is invoked with the old system array as its argument, and the new system array is returned. Then the short rows of the new array are made the correct length by concatenating the boundaries from the rows of the old system array onto them in a for-loop. In the loop we see that the values left_bound_elt and right_bound_elt are made into arrays of one element. This is necessary, as the concatenation operator requires that both its arguments be arrays. Finally, the top and bottom rows of the old system array are concatenated onto the widened core of the new system array. The result of these steps is an array the same size and shape as the old system array.This example also includes a use of the hybrid range generator "row in core at i". Use of this form of generator relieves us of the need to specify the index range of the array core, and yet still gives us an index value to use in the array index expressions within the loop.
These techniques are so powerful and useful that we will explore them further in an exercise.