3.4 IN Loops

Testing for Sets with Zero Elements

Where a loop lies naturally over the elements of a set, e.g. OBJECT, the loop should be preceded by a test of whether the set has zero elements: this ensures that the predicate is proved even if the loop is never executed:

IF     ?SIZE = SIZEOF OBJECT
AND    (   ?SIZE EQ 0
           OR  ?OBJECT IN OBJECT
                   AND < loop code >
       )

If we simply looped ?OBJECT IN OBJECT and OBJECT had zero elements, the statement would resolve UNKNOWN. The rule would then end UNKNOWN (unless there were an OR clause) and this could cause backtracking in the calling rule.

What Happens with Duplicate or Blank Entries

One concern which people often have about looping over sets is what happens when there are duplicate entries or entries are blank. These cause no difficulties. The only problem is in getting the index number of the current position in the set, which can be done thus:

IF     ?OBJECT IN OBJECT
AND        ?I = INDEXOF OBJECT(@)

The line ?I = INDEXOF OBJECT(@) obtains the current value of the loop counter (see section 2.b). It is so useful that it will often appear immediately after the start of an IN loop. Indeed, if it is to work, it must appear immediately after the start of the IN loop. For if it appears elsewhere, in particular after a predicate, it is possible that the position of the internal index in OBJECT may have been changed. WHILE loops can often be replaced directly by an IN loop followed by this statement.

Nested Loops over the Same Set

Note that as the loop counter is maintained separately for each loop (and is distinct from the pointer used by the SETIND command) it is possible to loop over a set twice in a nest, or even recursively:

IF     ?OBJECT IN OBJECT
AND        ?I = INDEXOF OBJECT(@)
     
AND        ?OBJECT2 IN OBJECT
AND            ?J = INDEXOF OBJECT(@)

Looping over Some Members of a Set

If a loop lies over some (but not all) members of a set it is still worth writing it as an IN loop over the entire set: this avoids any problems associated with the upper limit on a WHILE loop. Suppose that we want to ignore the first 100 elements of OBJECT. We can do this as follows:

IF     ?SIZE = SIZEOF OBJECT
AND    (   ?SIZE LT 100
           OR  ?OBJECT IN OBJECT
                   AND ?I = INDEXOF OBJECT(@)
                   AND ?I GE 100
                  
                   AND < loop code >
       )

This loops over ?OBJECT in OBJECT and then gets the internal index ?I of ?OBJECT. The test ?I GE 100 fails if we are looking at one of the first 100 elements of OBJECT, whereupon the interpreter backtracks to the loop over ?OBJECT and tries the next element. Once we are past the first 100 elements, the test ?I GE 100 succeeds and the rest of the loop code is executed.


Back                                Next
Comments