Unconditional Execution

As useful as the value accumulation constructs are, **LOOP** wouldn’t be a very good general-purpose iteration facility if there wasn’t a way to execute arbitrary Lisp code in the loop body.

The simplest way to execute arbitrary code within a loop body is with a do clause. Compared to the clauses I’ve described so far, with their prepositions and subclauses, do is a model of Yodaesque simplicity.7 A do clause consists of the word do (or doing) followed by one or more Lisp forms that are all evaluated when the do clause is. The do clause ends at the closing parenthesis of the loop or the next loop keyword.

For instance, to print the numbers from one to ten, you could write this:

  1. (loop for i from 1 to 10 do (print i))

Another, more dramatic, form of immediate execution is a return clause. This clause consists of the word return followed by a single Lisp form, which is evaluated, with the resulting value immediately returned as the value of the loop.

You can also break out of a loop in a do clause using any of Lisp’s normal control flow operators, such as **RETURN** and **RETURN-FROM**. Note that a return clause always returns from the immediately enclosing **LOOP** expression, while a **RETURN** or **RETURN-FROM** in a do clause can return from any enclosing expression. For instance, compare the following:

  1. (block outer
  2. (loop for i from 0 return 100) ; 100 returned from LOOP
  3. (print "This will print")
  4. 200) ==> 200

to this:

  1. (block outer
  2. (loop for i from 0 do (return-from outer 100)) ; 100 returned from BLOCK
  3. (print "This won't print")
  4. 200) ==> 100

The do and return clauses are collectively called the unconditional execution clauses.