CSC 153: Computer Science Fundamentals Grinnell College Spring, 2005
Laboratory Exercise Reading



This reading describes a useful approach for repeating processing, called iteration, using Scheme's do-expression. Iteration is useful problem-solving technique when processing must cycle through a sequence of steps, using successive values of variables.


Now that our toolbox contains local bindings to variables, we'll be seeing more and more cases in which it is useful to perform some procedure call or sequence of procedure calls repeatedly, for the sake of the side effects on structures or variables or for input or output. For example, the printing of the table of numbers and their square roots involved the repeated output of a line of a number and its root.

Most of these iterative constructions have a common form, and Scheme provides a special expression type to capture this form concisely and efficiently: the do-expression. A do-expression has the following structure:

(do loop-control-list
    (exit-test postlude)

Here's a simple example of a do-expression. We write a procedure display-countdown that takes one argument, a non-negative integer, and prints out the positive integers equal to or less than its argument, in descending order, one per line. Thus, the interaction might look as follows:

> (display-countdown 3)
Blast off!
The following code demonstrates a simple solution to this problem:
(define display-countdown
  (lambda (start)
  ;Pre-condition:  start is a nonnegative integer
  ;Post-condition:  prints the numbers start, ..., 1, 0 on separate lines
    (do ((remaining start (- remaining 1)))
        ((zero? remaining) "Blast off!")
      (display remaining)

Let's trace through the execution of a call to this procedure, using the above example (display-countdown 3):

As at another example of the use of do-expressions, here is a procedure that takes a list as argument and returns the list in reverse order. That is, we write out explicit code for Scheme's reverse procedure.

(define reverse-list
  (lambda (ls)
  ;Pre-condition:  ls is a list
  ;Post-condition:  returns the elements of ls in reverse order on a list
    (if (list? ls)
        (do ((new-ls '() (cons (car old-ls) new-ls))
             (old-ls ls (cdr old-ls)))
            ((null? old-ls) new-ls)

> (reverse-list '(3 1 4 1 5 9))
(9 5 1 4 1 3)

This time there are two loop-control variables: new-ls provides a list of elements already processed (starting with nil, while old-ls contains the list elements not yet processed. The iteration moves an element from old-ls to new-ls as part of the updating of variables. the body of the do-expression is null.

Overall, do-expressions can be used for clarity and conciseness in many of the situations.

This document is available on the World Wide Web as

created April 21, 1997 by John David Stone
last revised February 2, 2005 by Henry M. Walker
Valid HTML 4.01! Valid CSS!
For more information, please contact Henry M. Walker at