Repeating Operations

With these selectors, comparators and predicates, it becomes possible not only to choose between two or more alternatives, but also to repeat an action an indefinite number of times, based on the value of the comparison. As with most languages, there are two different approaches to repetition, recursion and iteration.

Recursion

Functions which call themselves until a given condition is reached are known as recursive functions. For example, the factorial function can be implemented as:

   (define (! n) 
     (cond ((not (integer? n)) 'Invalid-value)
           ((> 0 n) (! (abs n)))
           ((= 0 n) 1)
           (else (* n (! (- n 1))))))
  

Tail Recursion and Named Let

A standards-compliant Scheme compiler will correctly optimize a tail-recursive function into an iterative loop, so there is no need, in principle, for special iterative forms. To support iterative tail recursion, there is a special variant of (let), called the 'named let'. It consists of an identifier, followed by the loop's arguments ands their initializers, followed by an expression block. For example, the factorial function could be rewritten with a named let as such:

   (define (fact-named x)
     (cond ((not (integer? x)) 'invalid-argument)
           ((> 0 x)(fact-named (abs x)))
           (else 
            (let loop ((i 1)
                       (j 1))
              (if (>= i x)
               (* i j)
               (loop (+ 1 i) (* i j)))))))
  

Iteration

While the language strongly favors a recursive approach, Scheme does provide an iterative form, (do). The syntax for (do) is a group of local variable definitions, with optional step clauses to be applied on each iteration, followed by a loop test clause, then followed by the body of the loop (again, a block structure):

   (do ((variable (initializer) (increment)) 
        (test)
        (block))
  

For example, the factorial above could be written as

   (define (fact-do x)
       (cond ((not (integer? x)) 'invalid-argument)
             ((> 0 x) (fact-do (abs x)))
             (else 
              (do ((i 1 (+ 1 i))
                   (j 1 (* j i)))
                  ((> i x) j)))))
   

Contents Previous Next