Updated July 2015
To access elements from a collection without knowing the specific keys, an "iterator" is used. Iterators are special variables which act as pointers into a collection, allowing you to sequence through the elements of the collection. But because BASIC doesn’t normally allow pointers, our iterator behaves as if it were a temporary read-only variable containing the value of the current element.
To iterate through a collection, a "foreach" loop is used:
foreach $$i in $aryname({startkey}) ! fwd iterator
print $$i ! print the element value
print .key($$i) ! print the element key
next $$i
foreach’reverse $$j in $aryname() ! reverse iterator
print $$j ! print the element value
print .key($$j) ! print the element key
next $$j
Note: the above example assumes 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.field1 ! 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 there is no explicit ending value. The starting value is the first item in the collection (unless the optional startkey parameter is specified.) The concept is similar to sequencing through an indexed file until the end, except in this case if the specified startkey doesn’t exist, the entire sequence will be empty and the loop will be skipped.) To omit the startkey, use empty parens, e.g. $aryname().
• The order of the sequence will be according to the key. You can specify a reverse sequence by using the keyword foreach’reverse instead of foreach. (Note however that for the reverse iterator, the startkey option is ignored; it always starts at the highest key in the collection.)
• Adding, deleting or modifying keys while iterating will render the iterator unpredictable, and thus should be strictly avoided. You may, however, modify the values of elements as you iterate, keeping in mind that the iterator itself is read-only (so you would have to use the .key() function as in the examples above; further description below).
Within the loop, the iterator variable (e.g. $$i) will contain the value of the current element in the sequence. This is a read-only variable! And its type matches the element type of the ordered map (string for varstr, unformatted for varx).You can also access the key of the current element using the special "dot function" .key(<iterator>) as in the example foreach loop above. To modify an element's value, use the .key(<iterator>) function as the key. For example, the loop below would prefix each element with "Beautiful " and fold the capital name to upper case (assuming varstr elements):
foreach $$i in $capitals() ! fwd iterator
$capitals(.key($$i)) = "Beautiful " + ucs($$i)
next $$i
Here's another example which copies the ordered map $cap1 to a new ordered map $cap2:
dimx $cap1, ordmap(varstr;varstr)
...
! make copy of $cap1 into $cap2
dimx $cap2, ordmap(varstr;varstr)
foreach $$i in $cap1()
$cap2(.key($$i) = $$i
next $$i