The first example shows a loop that goes through all the checkboxes on a form and sets their value to false. An object reference to the form’s first control is assigned to a variable, and the reference is updated at the end of the loop to point to the next control in the tab order.

local oCtrl

oCtrl = form.first

do

   if oCtrl.className == "CHECKBOX" 

      oCtrl.value := false 

   endif 

   oCtrl := oCtrl.before 

until oCtrl == form.first

Because the DO...UNTIL checks the condition at the end of the loop, after the object reference has been updated, you can simply test if the reference has looped back to the beginning. To use the same test with a DO WHILE loop, you would have to maintain an extra flag to allow the loop to proceed the first time through.

The next example shows a basic loop that traverses all the rows in a rowset, referenced by the variable r:

if r.first()

   do 

      // Something to do to each row 

   until not r.next() 

endif

To traverse the rowset, you must start at the first row. The first( ) method attempts to reposition the row cursor to the first row in the rowset, returning true to indicate success. It would return false if there are no rows in the rowset—no rows at all, or no rows that match any active filter conditions—in which case the IF fails and the DO...UNTIL loop is not executed at all. If it returns true, then there must be at least one row, and the DO...UNTIL loop body is executed.

After the loop body is executed, the rowset’s next( ) method is called. It returns true unless it reaches the end-of-set. As long as it returns true, the logical NOT operator reverses the logical condition so that the UNTIL condition evaluates to false, and the loop continues. When it reaches the end-of-set, next( ) returns false, which gets reversed to true, satisfying the UNTIL condition and terminating the loop.

Compare the DO...UNTIL loop with the equivalent structure using DO WHILE:

r.first()

do while not r.endOfSet

   // Something to do to each row 

   r.next 

enddo

The rowset’s endOfSet property is true if the rowset is at the end-of-set. The return value from the first( ) method is not checked, because the endOfSet property is checked at the beginning of the DO WHILE loop. If first( ) fails, it leaves the rowset cursor at the end-of-set. The return value of next( ) is also not checked, for the same reason. However, this loop is slightly less efficient because it goes through the extra step of checking the endOfSet property instead of simply using the return value of next( ), which must be called to move to the next row.

This next example may look a bit odd:

do

until form.rowset.rlock()

but it simply retries the rlock( ) until it is successful. Note that the loop body is empty. You may want put a comment in the loop so you won’t have to think about it in the future:

do

// Wait for lock 

until form.rowset.rlock()

or you can use the semicolon to put two statements on the same line:

do; until form.rowset.rlock()