Updated February 2025
To access elements from a collection without knowing the specific keys, an “iterator” iterator is used. Iterators are special variables which receive the value of the next element of a collection each time through the loop.
To iterate through a collection, a FOREACH loop is used:
foreach $$i in $aryname({startkey,{endkey}}) ! fwd iterator
print $$i ! print the element value
print .key($$i) ! print the element key
next $$i
foreach’reverse $$j in $aryname({startkey,{endkey}}) ! reverse iterator
print $$j ! print the element value
print .key($$j) ! print the element key
next $$j
See Special ORDMAP Functions for a description of the .key() and other related functions.
The optional startkey and endkey values may be any kind of expressions that could appear on the right side of an assignment statement (aka "rvalues"), i.e. literals, variables, expressions with USING, function calls, etc. Numeric values are converted to string format, truncating to integer. Note that if there is not an exact match on startkey, the loop will iterator zero times, unlike in an ISAM lookup, where a failed initial key match will nevertheless affect the subsequent next operation. See History below for chronology of refinements.
Note: the above examples assume varstr elements; for varx elements, you wouldn’t try to print the $$i or $$j iterator values directly; instead you would assign them to a structure and then access the members, i.e.
Prodstruct = $$i ! copy iterator value to structure
print Prodstruct.field ! print a field of the element value
print .key($$j) ! print the element key
Although this is similar to a standard for/next loop, there are some noteworthy differences:
• | First, unlike the standard for/next loop where the loop variable must have been previously defined, in the FOREACH loop, the iterator variable ($$i in the example above) is created on the fly and exists just for the duration of the loop. Iterator variables must all start with $$ (which should not be used for any other variable type.) Since it is destroyed at the end of the loop, the same iterator variable name can be used in other FOREACH loops. |
• | Unlike the standard for/next loop, here the starting and ending values are optional; if omitted, the are effectively interpreted as the first and last items in the collection. The concept is similar to sequencing through an indexed file from a starting key (or one end of the file) to an ending key (or the opposite end of the file), except that if there is not an exact match on startkey, the entire loop will be skipped. To iterate the entire collection, use empty parens, e.g. $aryname(). |
• | The order of the sequence will be according to the key, either forward (foreach) or reverse (foreach'reverse). |
• | Modifications to the collection index (including deleting key-value pairs) during iteration should be strictly avoided. See Writeable Iterators for details. |
See Also
History
2023 November, A-Shell 7.0.1752.0: endkey parameter extended to grid maps.
2023 October, A-Shell 7.0.1751.0: startkey support added to FOREACH'REVERSE; endkey added for ordered map iteration.
2023 August, A-Shell 6.5.1739: In FOREACH, if the specified starting key is not found, the iteration now starts with the next key. Previously, the result would have been an empty iteration. In FOREACH'REVERSE, the starting key is now recognized whereas previously it was ignored. As with FOREACH, if not found, the iteration starts with the next key—i.e. the next one lower in the collating sequence.
2018 May, A-Shell 6.5.1636, compiler edit 859: the starting key in a FOREACH statement may now be any kind of expression. Previously, it only allowed a simple variable or a literal string or numeric constant; numeric literals were allowed but weren't converted to string and thus typically failed to match any items in the map.
Subtopics