Go to the previous, next section.

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@dots{}"
  (let (varlist)
    (while (true-or-false-test)
      body-of-while@dots{} )
      @dots{} )                     ; 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@dots{} ) 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.

Go to the previous, next section.