[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11. Loops and Recursion

Emacs Lisp has two primary ways to cause an expression, or a series of expressions, to be evaluated repeatedly: one uses a while loop, and the other uses recursion.

Repetition can be very valuable. For example, to move forward four sentences, you need only write a program that will move forward one sentence and then repeat the process four times. Since a computer does not get bored or tired, such repetitive action does not have the deleterious effects that excessive or the wrong kinds of repetition can have on humans.

People mostly write Emacs Lisp functions using while loops and their kin; but you can use recursion, which provides a very powerful way to think about and then to solve problems(8).

11.1 while  Causing a stretch of code to repeat.
11.2 Save your time: dolist and dotimes  
11.3 Recursion  Causing a function to call itself.
11.4 Looping Exercise  


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.1 while

The while special form tests whether the value returned by evaluating its first argument is true or false. This is similar to what the Lisp interpreter does with an if; what the interpreter does next, however, is different.

In a while expression, if the value returned by evaluating the first argument is false, the Lisp interpreter skips the rest of the expression (the body of the expression) and does not evaluate it. However, if the value is true, the Lisp interpreter evaluates the body of the expression and then again tests whether the first argument to while is true or false. If the value returned by evaluating the first argument is again true, the Lisp interpreter again evaluates the body of the expression.

The template for a while expression looks like this:

 
(while true-or-false-test
  body...)

Looping with while  Repeat so long as test returns true.
11.1.1 A while Loop and a List  A while loop that uses a list.
11.1.2 An Example: print-elements-of-list  Uses while, car, cdr.
11.1.3 A Loop with an Incrementing Counter  A loop with an incrementing counter.
11.1.4 Loop with a Decrementing Counter  A loop with a decrementing counter.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Looping with while

So long as the true-or-false-test of the while expression returns a true value when it is evaluated, the body is repeatedly evaluated. This process is called a loop since the Lisp interpreter repeats the same thing again and again, like an airplane doing a loop. When the result of evaluating the true-or-false-test is false, the Lisp interpreter does not evaluate the rest of the while expression and `exits the loop'.

Clearly, if the value returned by evaluating the first argument to while is always true, the body following will be evaluated again and again ... and again ... forever. Conversely, if the value returned is never true, the expressions in the body will never be evaluated. The craft of writing a while loop consists of choosing a mechanism such that the true-or-false-test returns true just the number of times that you want the subsequent expressions to be evaluated, and then have the test return false.

The value returned by evaluating a while is the value of the true-or-false-test. An interesting consequence of this is that a while loop that evaluates without error will return nil or false regardless of whether it has looped 1 or 100 times or none at all. A while expression that evaluates successfully never returns a true value! What this means is that while is always evaluated for its side effects, which is to say, the consequences of evaluating the expressions within the body of the while loop. This makes sense. It is not the mere act of looping that is desired, but the consequences of what happens when the expressions in the loop are repeatedly evaluated.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.1.1 A while Loop and a List

A common way to control a while loop is to test whether a list has any elements. If it does, the loop is repeated; but if it does not, the repetition is ended. Since this is an important technique, we will create a short example to illustrate it.

A simple way to test whether a list has elements is to evaluate the list: if it has no elements, it is an empty list and will return the empty list, (), which is a synonym for nil or false. On the other hand, a list with elements will return those elements when it is evaluated. Since Emacs Lisp considers as true any value that is not nil, a list that returns elements will test true in a while loop.

For example, you can set the variable empty-list to nil by evaluating the following setq expression:

 
(setq empty-list ())

After evaluating the setq expression, you can evaluate the variable empty-list in the usual way, by placing the cursor after the symbol and typing C-x C-e; nil will appear in your echo area:

 
empty-list

On the other hand, if you set a variable to be a list with elements, the list will appear when you evaluate the variable, as you can see by evaluating the following two expressions:

 
(setq animals '(gazelle giraffe lion tiger))

animals

Thus, to create a while loop that tests whether there are any items in the list animals, the first part of the loop will be written like this:

 
(while animals
       ...

When the while tests its first argument, the variable animals is evaluated. It returns a list. So long as the list has elements, the while considers the results of the test to be true; but when the list is empty, it considers the results of the test to be false.

To prevent the while loop from running forever, some mechanism needs to be provided to empty the list eventually. An oft-used technique is to have one of the subsequent forms in the while expression set the value of the list to be the CDR of the list. Each time the cdr function is evaluated, the list will be made shorter, until eventually only the empty list will be left. At this point, the test of the while loop will return false, and the arguments to the while will no longer be evaluated.

For example, the list of animals bound to the variable animals can be set to be the CDR of the original list with the following expression:

 
(setq animals (cdr animals))

If you have evaluated the previous expressions and then evaluate this expression, you will see (giraffe lion tiger) appear in the echo area. If you evaluate the expression again, (lion tiger) will appear in the echo area. If you evaluate it again and yet again, (tiger) appears and then the empty list, shown by nil.

A template for a while loop that uses the cdr function repeatedly to cause the true-or-false-test eventually to test false looks like this:

 
(while test-whether-list-is-empty
  body...
  set-list-to-cdr-of-list)

This test and use of cdr can be put together in a function that goes through a list and prints each element of the list on a line of its own.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.1.2 An Example: print-elements-of-list

The print-elements-of-list function illustrates a while loop with a list.

The function requires several lines for its output. If you are reading this in Emacs 21 or a later version, you can evaluate the following expression inside of Info, as usual.

If you are using an earlier version of Emacs, you need to copy the necessary expressions to your `*scratch*' buffer and evaluate them there. This is because the echo area had only one line in the earlier versions.

You can copy the expressions by marking the beginning of the region with C-SPC (set-mark-command), moving the cursor to the end of the region and then copying the region using M-w (copy-region-as-kill). In the `*scratch*' buffer, you can yank the expressions back by typing C-y (yank).

After you have copied the expressions to the `*scratch*' buffer, evaluate each expression in turn. Be sure to evaluate the last expression, (print-elements-of-list animals), by typing C-u C-x C-e, that is, by giving an argument to eval-last-sexp. This will cause the result of the evaluation to be printed in the `*scratch*' buffer instead of being printed in the echo area. (Otherwise you will see something like this in your echo area: ^Jgiraffe^J^Jgazelle^J^Jlion^J^Jtiger^Jnil, in which each `^J' stands for a `newline'.)

If you are using Emacs 21 or later, you can evaluate these expressions directly in the Info buffer, and the echo area will grow to show the results.

 
(setq animals '(gazelle giraffe lion tiger))

(defun print-elements-of-list (list)
  "Print each element of LIST on a line of its own."
  (while list
    (print (car list))
    (setq list (cdr list))))

(print-elements-of-list animals)

When you evaluate the three expressions in sequence, you will see this:

 
giraffe

gazelle

lion

tiger
nil

Each element of the list is printed on a line of its own (that is what the function print does) and then the value returned by the function is printed. Since the last expression in the function is the while loop, and since while loops always return nil, a nil is printed after the last element of the list.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.1.3 A Loop with an Incrementing Counter

A loop is not useful unless it stops when it ought. Besides controlling a loop with a list, a common way of stopping a loop is to write the first argument as a test that returns false when the correct number of repetitions are complete. This means that the loop must have a counter--an expression that counts how many times the loop repeats itself.

The test can be an expression such as (< count desired-number) which returns t for true if the value of count is less than the desired-number of repetitions and nil for false if the value of count is equal to or is greater than the desired-number. The expression that increments the count can be a simple setq such as (setq count (1+ count)), where 1+ is a built-in function in Emacs Lisp that adds 1 to its argument. (The expression (1+ count) has the same result as (+ count 1), but is easier for a human to read.)

The template for a while loop controlled by an incrementing counter looks like this:

 
set-count-to-initial-value
(while (< count desired-number)         ; true-or-false-test
  body...
  (setq count (1+ count)))              ; incrementer

Note that you need to set the initial value of count; usually it is set to 1.

Example with incrementing counter  Counting pebbles in a triangle.
The parts of the function definition  
Putting the function definition together  


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Example with incrementing counter

Suppose you are playing on the beach and decide to make a triangle of pebbles, putting one pebble in the first row, two in the second row, three in the third row and so on, like this:

 
               *
              * *
             * * *
            * * * *

(About 2500 years ago, Pythagoras and others developed the beginnings of number theory by considering questions such as this.)

Suppose you want to know how many pebbles you will need to make a triangle with 7 rows?

Clearly, what you need to do is add up the numbers from 1 to 7. There are two ways to do this; start with the smallest number, one, and add up the list in sequence, 1, 2, 3, 4 and so on; or start with the largest number and add the list going down: 7, 6, 5, 4 and so on. Because both mechanisms illustrate common ways of writing while loops, we will create two examples, one counting up and the other counting down. In this first example, we will start with 1 and add 2, 3, 4 and so on.

If you are just adding up a short list of numbers, the easiest way to do it is to add up all the numbers at once. However, if you do not know ahead of time how many numbers your list will have, or if you want to be prepared for a very long list, then you need to design your addition so that what you do is repeat a simple process many times instead of doing a more complex process once.

For example, instead of adding up all the pebbles all at once, what you can do is add the number of pebbles in the first row, 1, to the number in the second row, 2, and then add the total of those two rows to the third row, 3. Then you can add the number in the fourth row, 4, to the total of the first three rows; and so on.

The critical characteristic of the process is that each repetitive action is simple. In this case, at each step we add only two numbers, the number of pebbles in the row and the total already found. This process of adding two numbers is repeated again and again until the last row has been added to the total of all the preceding rows. In a more complex loop the repetitive action might not be so simple, but it will be simpler than doing everything all at once.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

The parts of the function definition

The preceding analysis gives us the bones of our function definition: first, we will need a variable that we can call total that will be the total number of pebbles. This will be the value returned by the function.

Second, we know that the function will require an argument: this argument will be the total number of rows in the triangle. It can be called number-of-rows.

Finally, we need a variable to use as a counter. We could call this variable counter, but a better name is row-number. That is because what the counter does is count rows, and a program should be written to be as understandable as possible.

When the Lisp interpreter first starts evaluating the expressions in the function, the value of total should be set to zero, since we have not added anything to it. Then the function should add the number of pebbles in the first row to the total, and then add the number of pebbles in the second to the total, and then add the number of pebbles in the third row to the total, and so on, until there are no more rows left to add.

Both total and row-number are used only inside the function, so they can be declared as local variables with let and given initial values. Clearly, the initial value for total should be 0. The initial value of row-number should be 1, since we start with the first row. This means that the let statement will look like this:

 
  (let ((total 0)
        (row-number 1))
    body...)

After the internal variables are declared and bound to their initial values, we can begin the while loop. The expression that serves as the test should return a value of t for true so long as the row-number is less than or equal to the number-of-rows. (If the expression tests true only so long as the row number is less than the number of rows in the triangle, the last row will never be added to the total; hence the row number has to be either less than or equal to the number of rows.)

Lisp provides the <= function that returns true if the value of its first argument is less than or equal to the value of its second argument and false otherwise. So the expression that the while will evaluate as its test should look like this:

 
(<= row-number number-of-rows)

The total number of pebbles can be found by repeatedly adding the number of pebbles in a row to the total already found. Since the number of pebbles in the row is equal to the row number, the total can be found by adding the row number to the total. (Clearly, in a more complex situation, the number of pebbles in the row might be related to the row number in a more complicated way; if this were the case, the row number would be replaced by the appropriate expression.)

 
(setq total (+ total row-number))

What this does is set the new value of total to be equal to the sum of adding the number of pebbles in the row to the previous total.

After setting the value of total, the conditions need to be established for the next repetition of the loop, if there is one. This is done by incrementing the value of the row-number variable, which serves as a counter. After the row-number variable has been incremented, the true-or-false-test at the beginning of the while loop tests whether its value is still less than or equal to the value of the number-of-rows and if it is, adds the new value of the row-number variable to the total of the previous repetition of the loop.

The built-in Emacs Lisp function 1+ adds 1 to a number, so the row-number variable can be incremented with this expression:

 
(setq row-number (1+ row-number))


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Putting the function definition together

We have created the parts for the function definition; now we need to put them together.

First, the contents of the while expression:

 
(while (<= row-number number-of-rows)   ; true-or-false-test
  (setq total (+ total row-number))
  (setq row-number (1+ row-number)))    ; incrementer

Along with the let expression varlist, this very nearly completes the body of the function definition. However, it requires one final element, the need for which is somewhat subtle.

The final touch is to place the variable total on a line by itself after the while expression. Otherwise, the value returned by the whole function is the value of the last expression that is evaluated in the body of the let, and this is the value returned by the while, which is always nil.

This may not be evident at first sight. It almost looks as if the incrementing expression is the last expression of the whole function. But that expression is part of the body of the while; it is the last element of the list that starts with the symbol while. Moreover, the whole of the while loop is a list within the body of the let.

In outline, the function will look like this:

 
(defun name-of-function (argument-list)
  "documentation..."
  (let (varlist)
    (while (true-or-false-test)
      body-of-while... )
    ... )                     ; Need final expression here.

The result of evaluating the let is what is going to be returned by the defun since the let is not embedded within any containing list, except for the defun as a whole. However, if the while is the last element of the let expression, the function will always return nil. This is not what we want! Instead, what we want is the value of the variable total. This is returned by simply placing the symbol as the last element of the list starting with let. It gets evaluated after the preceding elements of the list are evaluated, which means it gets evaluated after it has been assigned the correct value for the total.

It may be easier to see this by printing the list starting with let all on one line. This format makes it evident that the varlist and while expressions are the second and third elements of the list starting with let, and the total is the last element:

 
(let (varlist) (while (true-or-false-test) body-of-while... ) total)

Putting everything together, the triangle function definition looks like this:

 
(defun triangle (number-of-rows)    ; Version with
                                    ;   incrementing counter.
  "Add up the number of pebbles in a triangle.
The first row has one pebble, the second row two pebbles,
the third row three pebbles, and so on.
The argument is NUMBER-OF-ROWS."
  (let ((total 0)
        (row-number 1))
    (while (<= row-number number-of-rows)
      (setq total (+ total row-number))
      (setq row-number (1+ row-number)))
    total))

After you have installed triangle by evaluating the function, you can try it out. Here are two examples:

 
(triangle 4)

(triangle 7)

The sum of the first four numbers is 10 and the sum of the first seven numbers is 28.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.1.4 Loop with a Decrementing Counter

Another common way to write a while loop is to write the test so that it determines whether a counter is greater than zero. So long as the counter is greater than zero, the loop is repeated. But when the counter is equal to or less than zero, the loop is stopped. For this to work, the counter has to start out greater than zero and then be made smaller and smaller by a form that is evaluated repeatedly.

The test will be an expression such as (> counter 0) which returns t for true if the value of counter is greater than zero, and nil for false if the value of counter is equal to or less than zero. The expression that makes the number smaller and smaller can be a simple setq such as (setq counter (1- counter)), where 1- is a built-in function in Emacs Lisp that subtracts 1 from its argument.

The template for a decrementing while loop looks like this:

 
(while (> counter 0)                    ; true-or-false-test
  body...
  (setq counter (1- counter)))          ; decrementer

Example with decrementing counter  More pebbles on the beach.
The parts of the function definition   
Putting the function definition together   


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Example with decrementing counter

To illustrate a loop with a decrementing counter, we will rewrite the triangle function so the counter decreases to zero.

This is the reverse of the earlier version of the function. In this case, to find out how many pebbles are needed to make a triangle with 3 rows, add the number of pebbles in the third row, 3, to the number in the preceding row, 2, and then add the total of those two rows to the row that precedes them, which is 1.

Likewise, to find the number of pebbles in a triangle with 7 rows, add the number of pebbles in the seventh row, 7, to the number in the preceding row, which is 6, and then add the total of those two rows to the row that precedes them, which is 5, and so on. As in the previous example, each addition only involves adding two numbers, the total of the rows already added up and the number of pebbles in the row that is being added to the total. This process of adding two numbers is repeated again and again until there are no more pebbles to add.

We know how many pebbles to start with: the number of pebbles in the last row is equal to the number of rows. If the triangle has seven rows, the number of pebbles in the last row is 7. Likewise, we know how many pebbles are in the preceding row: it is one less than the number in the row.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

The parts of the function definition

We start with three variables: the total number of rows in the triangle; the number of pebbles in a row; and the total number of pebbles, which is what we want to calculate. These variables can be named number-of-rows, number-of-pebbles-in-row, and total, respectively.

Both total and number-of-pebbles-in-row are used only inside the function and are declared with let. The initial value of total should, of course, be zero. However, the initial value of number-of-pebbles-in-row should be equal to the number of rows in the triangle, since the addition will start with the longest row.

This means that the beginning of the let expression will look like this:

 
(let ((total 0)
      (number-of-pebbles-in-row number-of-rows))
  body...)

The total number of pebbles can be found by repeatedly adding the number of pebbles in a row to the total already found, that is, by repeatedly evaluating the following expression:

 
(setq total (+ total number-of-pebbles-in-row))

After the number-of-pebbles-in-row is added to the total, the number-of-pebbles-in-row should be decremented by one, since the next time the loop repeats, the preceding row will be added to the total.

The number of pebbles in a preceding row is one less than the number of pebbles in a row, so the built-in Emacs Lisp function 1- can be used to compute the number of pebbles in the preceding row. This can be done with the following expression:

 
(setq number-of-pebbles-in-row
      (1- number-of-pebbles-in-row))

Finally, we know that the while loop should stop making repeated additions when there are no pebbles in a row. So the test for the while loop is simply:

 
(while (> number-of-pebbles-in-row 0)


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Putting the function definition together

We can put these expressions together to create a function definition that works. However, on examination, we find that one of the local variables is unneeded!

The function definition looks like this:

 
;;; First subtractive version.
(defun triangle (number-of-rows)
  "Add up the number of pebbles in a triangle."
  (let ((total 0)
        (number-of-pebbles-in-row number-of-rows))
    (while (> number-of-pebbles-in-row 0)
      (setq total (+ total number-of-pebbles-in-row))
      (setq number-of-pebbles-in-row
            (1- number-of-pebbles-in-row)))
    total))

As written, this function works.

However, we do not need number-of-pebbles-in-row.

When the triangle function is evaluated, the symbol number-of-rows will be bound to a number, giving it an initial value. That number can be changed in the body of the function as if it were a local variable, without any fear that such a change will effect the value of the variable outside of the function. This is a very useful characteristic of Lisp; it means that the variable number-of-rows can be used anywhere in the function where number-of-pebbles-in-row is used.

Here is a second version of the function written a bit more cleanly:

 
(defun triangle (number)                ; Second version.
  "Return sum of numbers 1 through NUMBER inclusive."
  (let ((total 0))
    (while (> number 0)
      (setq total (+ total number))
      (setq number (1- number)))
    total))

In brief, a properly written while loop will consist of three parts:

  1. A test that will return false after the loop has repeated itself the correct number of times.

  2. An expression the evaluation of which will return the value desired after being repeatedly evaluated.

  3. An expression to change the value passed to the true-or-false-test so that the test returns false after the loop has repeated itself the right number of times.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.2 Save your time: dolist and dotimes

In addition to while, both dolist and dotimes provide for looping. Sometimes these are quicker to write than the equivalent while loop. Both are Lisp macros. (See section `Macros' in The GNU Emacs Lisp Reference Manual. )

dolist works like a while loop that `CDRs down a list': dolist automatically shortens the list each time it loops--takes the CDR of the list--and binds the CAR of each shorter version of the list to the first of its arguments.

dotimes loops a specific number of time: you specify the number.

The dolist Macro  
The dotimes Macro  


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

The dolist Macro

Suppose, for example, you want to reverse a list, so that "first" "second" "third" becomes "third" "second" "first".

In practice, you would use the reverse function, like this:

 
(setq animals '(gazelle giraffe lion tiger))

(reverse animals)

Here is how you could reverse the list using a while loop:

 
(setq animals '(gazelle giraffe lion tiger))

(defun reverse-list-with-while (list)
  "Using while, reverse the order of LIST."
  (let (value)  ; make sure list starts empty
    (while list
      (setq value (cons (car list) value))
      (setq list (cdr list)))
    value))

(reverse-list-with-while animals)

And here is how you could use the dolist macro:

 
(setq animals '(gazelle giraffe lion tiger))

(defun reverse-list-with-dolist (list)
  "Using dolist, reverse the order of LIST."
  (let (value)  ; make sure list starts empty
    (dolist (element list value)
      (setq value (cons element value)))))

(reverse-list-with-dolist animals)

In Info, you can place your cursor after the closing parenthesis of each expression and type C-x C-e; in each case, you should see

 
(tiger lion giraffe gazelle)

in the echo area.

For this example, the existing reverse function is obviously best. The while loop is just like our first example (see section A while Loop and a List). The while first checks whether the list has elements; if so, it constructs a new list by adding the first element of the list to the existing list (which in the first iteration of the loop is nil). Since the second element is prepended in front of the first element, and the third element is prepended in front of the second element, the list is reversed.

In the expression using a while loop, the (setq list (cdr list)) expression shortens the list, so the while loop eventually stops. In addition, it provides the cons expression with a new first element by creating a new and shorter list at each repetition of the loop.

The dolist expression does very much the same as the while expression, except that the dolist macro does some of the work you have to do when writing a while expression.

Like a while loop, a dolist loops. What is different is that it automatically shortens the list each time it loops -- it `CDRs down the list' on its own -- and it automatically binds the CAR of each shorter version of the list to the first of its arguments.

In the example, the CAR of each shorter version of the list is referred to using the symbol `element', the list itself is called `list', and the value returned is called `value'. The remainder of the dolist expression is the body.

The dolist expression binds the CAR of each shorter version of the list to element and then evaluates the body of the expression; and repeats the loop. The result is returned in value.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

The dotimes Macro

The dotimes macro is similar to dolist, except that it loops a specific number of times.

The first argument to dotimes is assigned the numbers 0, 1, 2 and so forth each time around the loop, and the value of the third argument is returned. You need to provide the value of the second argument, which is how many times the macro loops.

For example, the following binds the numbers from 0 up to, but not including, the number 3 to the first argument, number, and then constructs a list of the three numbers. (The first number is 0, the second number is 1, and the third number is 2; this makes a total of three numbers in all, starting with zero as the first number.)

 
(let (value)      ; otherwise a value is a void variable
  (dotimes (number 3 value)
    (setq value (cons number value))))

=> (2 1 0)

dotimes returns value, so the way to use dotimes is to operate on some expression number number of times and then return the result, either as a list or an atom.

Here is an example of a defun that uses dotimes to add up the number of pebbles in a triangle.

 
(defun triangle-using-dotimes (number-of-rows)
  "Using dotimes, add up the number of pebbles in a triangle."
(let ((total 0))  ; otherwise a total is a void variable
  (dotimes (number number-of-rows total)
    (setq total (+ total (1+ number))))))

(triangle-using-dotimes 4)


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.3 Recursion

A recursive function contains code that tells the Lisp interpreter to call a program that runs exactly like itself, but with slightly different arguments. The code runs exactly the same because it has the same name. However, even though it has the same name, it is not the same thread of execution. It is different. In the jargon, it is a different `instance'.

Eventually, if the program is written correctly, the `slightly different arguments' will become sufficiently different from the first arguments that the final instance will stop.

11.3.1 Building Robots: Extending the Metaphor  Same model, different serial number ...
11.3.2 The Parts of a Recursive Definition  Walk until you stop ...
11.3.3 Recursion with a List  Using a list as the test whether to recurse.
11.3.4 Recursion in Place of a Counter  
11.3.5 Recursion Example Using cond  
11.3.6 Recursive Patterns  Often used templates.
11.3.7 Recursion without Deferments  Don't store up work ...
11.3.8 No Deferment Solution  


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.3.1 Building Robots: Extending the Metaphor

It is sometimes helpful to think of a running program as a robot that does a job. In doing its job, a recursive function calls on a second robot to help it. The second robot is identical to the first in every way, except that the second robot helps the first and has been passed different arguments than the first.

In a recursive function, the second robot may call a third; and the third may call a fourth, and so on. Each of these is a different entity; but all are clones.

Since each robot has slightly different instructions--the arguments will differ from one robot to the next--the last robot should know when to stop.

Let's expand on the metaphor in which a computer program is a robot.

A function definition provides the blueprints for a robot. When you install a function definition, that is, when you evaluate a defun special form, you install the necessary equipment to build robots. It is as if you were in a factory, setting up an assembly line. Robots with the same name are built according to the same blueprints. So they have, as it were, the same `model number', but a different `serial number'.

We often say that a recursive function `calls itself'. What we mean is that the instructions in a recursive function cause the Lisp interpreter to run a different function that has the same name and does the same job as the first, but with different arguments.

It is important that the arguments differ from one instance to the next; otherwise, the process will never stop.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.3.2 The Parts of a Recursive Definition

A recursive function typically contains a conditional expression which has three parts:

  1. A true-or-false-test that determines whether the function is called again, here called the do-again-test.

  2. The name of the function. When this name is called, a new instance of the function--a new robot, as it were--is created and told what to do.

  3. An expression that returns a different value each time the function is called, here called the next-step-expression. Consequently, the argument (or arguments) passed to the new instance of the function will be different from that passed to the previous instance. This causes the conditional expression, the do-again-test, to test false after the correct number of repetitions.

Recursive functions can be much simpler than any other kind of function. Indeed, when people first start to use them, they often look so mysteriously simple as to be incomprehensible. Like riding a bicycle, reading a recursive function definition takes a certain knack which is hard at first but then seems simple.

There are several different common recursive patterns. A very simple pattern looks like this:

 
(defun name-of-recursive-function (argument-list)
  "documentation..."
  (if do-again-test
    body...
    (name-of-recursive-function
         next-step-expression)))

Each time a recursive function is evaluated, a new instance of it is created and told what to do. The arguments tell the instance what to do.

An argument is bound to the value of the next-step-expression. Each instance runs with a different value of the next-step-expression.

The value in the next-step-expression is used in the do-again-test.

The value returned by the next-step-expression is passed to the new instance of the function, which evaluates it (or some transmogrification of it) to determine whether to continue or stop. The next-step-expression is designed so that the do-again-test returns false when the function should no longer be repeated.

The do-again-test is sometimes called the stop condition, since it stops the repetitions when it tests false.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.3.3 Recursion with a List

The example of a while loop that printed the elements of a list of numbers can be written recursively. Here is the code, including an expression to set the value of the variable animals to a list.

If you are using Emacs 20 or before, this example must be copied to the `*scratch*' buffer and each expression must be evaluated there. Use C-u C-x C-e to evaluate the (print-elements-recursively animals) expression so that the results are printed in the buffer; otherwise the Lisp interpreter will try to squeeze the results into the one line of the echo area.

Also, place your cursor immediately after the last closing parenthesis of the print-elements-recursively function, before the comment. Otherwise, the Lisp interpreter will try to evaluate the comment.

If you are using Emacs 21 or later, you can evaluate this expression directly in Info.

 
(setq animals '(gazelle giraffe lion tiger))

(defun print-elements-recursively (list)
  "Print each element of LIST on a line of its own.
Uses recursion."
  (if list                              ; do-again-test
      (progn
        (print (car list))              ; body
        (print-elements-recursively     ; recursive call
         (cdr list)))))                 ; next-step-expression

(print-elements-recursively animals)

The print-elements-recursively function first tests whether there is any content in the list; if there is, the function prints the first element of the list, the CAR of the list. Then the function `invokes itself', but gives itself as its argument, not the whole list, but the second and subsequent elements of the list, the CDR of the list.

Put another way, if the list is not empty, the function invokes another instance of code that is similar to the initial code, but is a different thread of execution, with different arguments than the first instance.

Put in yet another way, if the list is not empty, the first robot assemblies a second robot and tells it what to do; the second robot is a different individual from the first, but is the same model.

When the second evaluation occurs, the if expression is evaluated and if true, prints the first element of the list it receives as its argument (which is the second element of the original list). Then the function `calls itself' with the CDR of the list it is invoked with, which (the second time around) is the CDR of the CDR of the original list.

Note that although we say that the function `calls itself', what we mean is that the Lisp interpreter assembles and instructs a new instance of the program. The new instance is a clone of the first, but is a separate individual.

Each time the function `invokes itself', it invokes itself on a shorter version of the original list. It creates a new instance that works on a shorter list.

Eventually, the function invokes itself on an empty list. It creates a new instance whose argument is nil. The conditional expression tests the value of list. Since the value of list is nil, the if expression tests false so the then-part is not evaluated. The function as a whole then returns nil.

When you evaluate (print-elements-recursively animals) in the `*scratch*' buffer, you see this result:

 
giraffe

gazelle

lion

tiger
nil


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.3.4 Recursion in Place of a Counter

The triangle function described in a previous section can also be written recursively. It looks like this:

 
(defun triangle-recursively (number)
  "Return the sum of the numbers 1 through NUMBER inclusive.
Uses recursion."
  (if (= number 1)                    ; do-again-test
      1                               ; then-part
    (+ number                         ; else-part
       (triangle-recursively          ; recursive call
        (1- number)))))               ; next-step-expression

(triangle-recursively 7)

You can install this function by evaluating it and then try it by evaluating (triangle-recursively 7). (Remember to put your cursor immediately after the last parenthesis of the function definition, before the comment.) The function evaluates to 28.

To understand how this function works, let's consider what happens in the various cases when the function is passed 1, 2, 3, or 4 as the value of its argument.

An argument of 1 or 2  
An argument of 3 or 4  


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

An argument of 1 or 2

First, what happens if the value of the argument is 1?

The function has an if expression after the documentation string. It tests whether the value of number is equal to 1; if so, Emacs evaluates the then-part of the if expression, which returns the number 1 as the value of the function. (A triangle with one row has one pebble in it.)

Suppose, however, that the value of the argument is 2. In this case, Emacs evaluates the else-part of the if expression.

The else-part consists of an addition, the recursive call to triangle-recursively and a decrementing action; and it looks like this:

 
(+ number (triangle-recursively (1- number)))

When Emacs evaluates this expression, the innermost expression is evaluated first; then the other parts in sequence. Here are the steps in detail:

Step 1 Evaluate the innermost expression.

The innermost expression is (1- number) so Emacs decrements the value of number from 2 to 1.

Step 2 Evaluate the triangle-recursively function.

The Lisp interpreter creates an individual instance of triangle-recursively. It does not matter that this function is contained within itself. Emacs passes the result Step 1 as the argument used by this instance of the triangle-recursively function

In this case, Emacs evaluates triangle-recursively with an argument of 1. This means that this evaluation of triangle-recursively returns 1.

Step 3 Evaluate the value of number.

The variable number is the second element of the list that starts with +; its value is 2.

Step 4 Evaluate the + expression.

The + expression receives two arguments, the first from the evaluation of number (Step 3) and the second from the evaluation of triangle-recursively (Step 2).

The result of the addition is the sum of 2 plus 1, and the number 3 is returned, which is correct. A triangle with two rows has three pebbles in it.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

An argument of 3 or 4

Suppose that triangle-recursively is called with an argument of 3.

Step 1 Evaluate the do-again-test.

The if expression is evaluated first. This is the do-again test and returns false, so the else-part of the if expression is evaluated. (Note that in this example, the do-again-test causes the function to call itself when it tests false, not when it tests true.)

Step 2 Evaluate the innermost expression of the else-part.

The innermost expression of the else-part is evaluated, which decrements 3 to 2. This is the next-step-expression.

Step 3 Evaluate the triangle-recursively function.

The number 2 is passed to the triangle-recursively function.

We know what happens when Emacs evaluates triangle-recursively with an argument of 2. After going through the sequence of actions described earlier, it returns a value of 3. So that is what will happen here.

Step 4 Evaluate the addition.

3 will be passed as an argument to the addition and will be added to the number with which the function was called, which is 3.

The value returned by the function as a whole will be 6.

Now that we know what will happen when triangle-recursively is called with an argument of 3, it is evident what will happen if it is called with an argument of 4:

In the recursive call, the evaluation of

 
(triangle-recursively (1- 4))

will return the value of evaluating

 
(triangle-recursively 3)

which is 6 and this value will be added to 4 by the addition in the third line.

The value returned by the function as a whole will be 10.

Each time triangle-recursively is evaluated, it evaluates a version of itself--a different instance of itself--with a smaller argument, until the argument is small enough so that it does not evaluate itself.

Note that this particular design for a recursive function requires that operations be deferred.

Before (triangle-recursively 7) can calculate its answer, it must call (triangle-recursively 6); and before (triangle-recursively 6) can calculate its answer, it must call (triangle-recursively 5); and so on. That is to say, the calculation that (triangle-recursively 7) makes must be deferred until (triangle-recursively 6) makes its calculation; and (triangle-recursively 6) must defer until (triangle-recursively 5) completes; and so on.

If each of these instances of triangle-recursively are thought of as different robots, the first robot must wait for the second to complete its job, which must wait until the third completes, and so on.

There is a way around this kind of waiting, which we will discuss in Recursion without Deferments.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.3.5 Recursion Example Using cond

The version of triangle-recursively described earlier is written with the if special form. It can also be written using another special form called cond. The name of the special form cond is an abbreviation of the word `conditional'.

Although the cond special form is not used as often in the Emacs Lisp sources as if, it is used often enough to justify explaining it.

The template for a cond expression looks like this:

 
(cond
 body...)

where the body is a series of lists.

Written out more fully, the template looks like this:

 
(cond
 (first-true-or-false-test first-consequent)
 (second-true-or-false-test second-consequent)
 (third-true-or-false-test third-consequent)
  ...)

When the Lisp interpreter evaluates the cond expression, it evaluates the first element (the CAR or true-or-false-test) of the first expression in a series of expressions within the body of the cond.

If the true-or-false-test returns nil the rest of that expression, the consequent, is skipped and the true-or-false-test of the next expression is evaluated. When an expression is found whose true-or-false-test returns a value that is not nil, the consequent of that expression is evaluated. The consequent can be one or more expressions. If the consequent consists of more than one expression, the expressions are evaluated in sequence and the value of the last one is returned. If the expression does not have a consequent, the value of the true-or-false-test is returned.

If none of the true-or-false-tests test true, the cond expression returns nil.

Written using cond, the triangle function looks like this:

 
(defun triangle-using-cond (number)
  (cond ((<= number 0) 0)
        ((= number 1) 1)
        ((> number 1)
         (+ number (triangle-using-cond (1- number))))))

In this example, the cond returns 0 if the number is less than or equal to 0, it returns 1 if the number is 1 and it evaluates (+ number (triangle-using-cond (1- number))) if the number is greater than 1.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.3.6 Recursive Patterns

Here are three common recursive patterns. Each involves a list. Recursion does not need to involve lists, but Lisp is designed for lists and this provides a sense of its primal capabilities.

Recursive Pattern: every  
Recursive Pattern: accumulate  
Recursive Pattern: keep  


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Recursive Pattern: every

In the every recursive pattern, an action is performed on every element of a list.

The basic pattern is:

Here is example:

 
(defun square-each (numbers-list)
  "Square each of a NUMBERS LIST, recursively."
  (if (not numbers-list)                ; do-again-test
      nil
    (cons
     (* (car numbers-list) (car numbers-list))
     (square-each (cdr numbers-list))))) ; next-step-expression

(square-each '(1 2 3))
    => (1 4 9)

If numbers-list is empty, do nothing. But if it has content, construct a list combining the square of the first number in the list with the result of the recursive call.

(The example follows the pattern exactly: nil is returned if the numbers' list is empty. In practice, you would write the conditional so it carries out the action when the numbers' list is not empty.)

The print-elements-recursively function (see section Recursion with a List) is another example of an every pattern, except in this case, rather than bring the results together using cons, we print each element of output.

The print-elements-recursively function looks like this:

 
(setq animals '(gazelle giraffe lion tiger))

(defun print-elements-recursively (list)
  "Print each element of LIST on a line of its own.
Uses recursion."
  (if list                              ; do-again-test
      (progn
        (print (car list))              ; body
        (print-elements-recursively     ; recursive call
         (cdr list)))))                 ; next-step-expression

(print-elements-recursively animals)

The pattern for print-elements-recursively is:


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Recursive Pattern: accumulate

Another recursive pattern is called the accumulate pattern. In the accumulate recursive pattern, an action is performed on every element of a list and the result of that action is accumulated with the results of performing the action on the other elements.

This is very like the `every' pattern using cons, except that cons is not used, but some other combiner.

The pattern is:

Here is an example:

 
(defun add-elements (numbers-list)
  "Add the elements of NUMBERS-LIST together."
  (if (not numbers-list)
      0
    (+ (car numbers-list) (add-elements (cdr numbers-list)))))

(add-elements '(1 2 3 4))
    => 10

See section Making a List of Files, for an example of the accumulate pattern.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Recursive Pattern: keep

A third recursive pattern is called the keep pattern. In the keep recursive pattern, each element of a list is tested; the element is acted on and the results are kept only if the element meets a criterion.

Again, this is very like the `every' pattern, except the element is skipped unless it meets a criterion.

The pattern has three parts:

Here is an example that uses cond:

 
(defun keep-three-letter-words (word-list)
  "Keep three letter words in WORD-LIST."
  (cond
   ;; First do-again-test: stop-condition
   ((not word-list) nil)

   ;; Second do-again-test: when to act
   ((eq 3 (length (symbol-name (car word-list))))
    ;; combine acted-on element with recursive call on shorter list
    (cons (car word-list) (keep-three-letter-words (cdr word-list))))

   ;; Third do-again-test: when to skip element;
   ;;   recursively call shorter list with next-step expression
   (t  (keep-three-letter-words (cdr word-list)))))

(keep-three-letter-words '(one two three four five six))
    => (one two six)

It goes without saying that you need not use nil as the test for when to stop; and you can, of course, combine these patterns.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.3.7 Recursion without Deferments

Let's consider again what happens with the triangle-recursively function. We will find that the intermediate calculations are deferred until all can be done.

Here is the function definition:

 
(defun triangle-recursively (number)
  "Return the sum of the numbers 1 through NUMBER inclusive.
Uses recursion."
  (if (= number 1)                    ; do-again-test
      1                               ; then-part
    (+ number                         ; else-part
       (triangle-recursively          ; recursive call
        (1- number)))))               ; next-step-expression

What happens when we call this function with a argument of 7?

The first instance of the triangle-recursively function adds the number 7 to the value returned by a second instance of triangle-recursively, an instance that has been passed an argument of 6. That is to say, the first calculation is:

 
(+ 7 (triangle-recursively 6)

The first instance of triangle-recursively---you may want to think of it as a little robot--cannot complete its job. It must hand off the calculation for (triangle-recursively 6) to a second instance of the program, to a second robot. This second individual is completely different from the first one; it is, in the jargon, a `different instantiation'. Or, put another way, it is a different robot. It is the same model as the first; it calculates triangle numbers recursively; but it has a different serial number.

And what does (triangle-recursively 6) return? It returns the number 6 added to the value returned by evaluating triangle-recursively with an argument of 5. Using the robot metaphor, it asks yet another robot to help it.

Now the total is:

 
(+ 7 6 (triangle-recursively 5)

And what happens next?

 
(+ 7 6 5 (triangle-recursively 4)

Each time triangle-recursively is called, except for the last time, it creates another instance of the program--another robot--and asks it to make a calculation.

Eventually, the full addition is set up and performed:

 
(+ 7 6 5 4 3 2 1)

This design for the function defers the calculation of the first step until the second can be done, and defers that until the third can be done, and so on. Each deferment means the computer must remember what is being waited on. This is not a problem when there are only a few steps, as in this example. But it can be a problem when there are more steps.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.3.8 No Deferment Solution

The solution to the problem of deferred operations is to write in a manner that does not defer operations(9). This requires writing to a different pattern, often one that involves writing two function definitions, an `initialization' function and a `helper' function.

The `initialization' function sets up the job; the `helper' function does the work.

Here are the two function definitions for adding up numbers. They are so simple, I find them hard to understand.

 
(defun triangle-initialization (number)
  "Return the sum of the numbers 1 through NUMBER inclusive.
This is the `initialization' component of a two function
duo that uses recursion."
  (triangle-recursive-helper 0 0 number))

 
(defun triangle-recursive-helper (sum counter number)
  "Return SUM, using COUNTER, through NUMBER inclusive.
This is the `helper' component of a two function duo
that uses recursion."
  (if (> counter number)
      sum
    (triangle-recursive-helper (+ sum counter)  ; sum
                               (1+ counter)     ; counter
                               number)))        ; number

Install both function definitions by evaluating them, then call triangle-initialization with 2 rows:

 
(triangle-initialization 2)
    => 3

The `initialization' function calls the first instance of the `helper' function with three arguments: zero, zero, and a number which is the number of rows in the triangle.

The first two arguments passed to the `helper' function are initialization values. These values are changed when triangle-recursive-helper invokes new instances.(10)

Let's see what happens when we have a triangle that has one row. (This triangle will have one pebble in it!)

triangle-initialization will call its helper with the arguments 0 0 1. That function will run the conditional test whether (> counter number):

 
(> 0 1)

and find that the result is false, so it will invoke the then-part of the if clause:

 
    (triangle-recursive-helper
     (+ sum counter)  ; sum plus counter => sum
     (1+ counter)     ; increment counter => counter
     number)          ; number stays the same

which will first compute:

 
(triangle-recursive-helper (+ 0 0)  ; sum
                           (1+ 0)   ; counter
                           1)       ; number
which is:

(triangle-recursive-helper 0 1 1)

Again, (> counter number) will be false, so again, the Lisp interpreter will evaluate triangle-recursive-helper, creating a new instance with new arguments.

This new instance will be;

 
    (triangle-recursive-helper
     (+ sum counter)  ; sum plus counter => sum
     (1+ counter)     ; increment counter => counter
     number)          ; number stays the same

which is:

(triangle-recursive-helper 1 2 1)

In this case, the (> counter number) test will be true! So the instance will return the value of the sum, which will be 1, as expected.

Now, let's pass triangle-initialization an argument of 2, to find out how many pebbles there are in a triangle with two rows.

That function calls (triangle-recursive-helper 0 0 2).

In stages, the instances called will be:

 
                          sum counter number
(triangle-recursive-helper 0    1       2)

(triangle-recursive-helper 1    2       2)

(triangle-recursive-helper 3    3       2)

When the last instance is called, the (> counter number) test will be true, so the instance will return the value of sum, which will be 3.

This kind of pattern helps when you are writing functions that can use many resources in a computer.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.4 Looping Exercise


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Dohn Arms on March, 6 2005 using texi2html