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.