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.
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...)
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.
while
loop that uses a list.
while
, car
, cdr
.
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 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 '(giraffe gazelle 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, 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 (gazelle 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.
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. Since the echo
area is only one line, we cannot illustrate how it works in the same
way we have been illustrating functions in the past, by evaluating
them inside Info. Instead, you need to copy the necessary
expressions to your `*scratch*' buffer and evaluate them there.
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 the newline that in the `*scratch*'
buffer puts each word on its own line. You can evaluate these
expressions right now in the Info buffer, if you like, to see this
effect.)
(setq animals '(giraffe gazelle 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 in the `*scratch*' buffer, this will be printed in the buffer:
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.
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.
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.
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 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))
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.
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 one of the forms 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
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.
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)
Putting these expressions together, we have a function definition that 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, it turns out that one of the local variables,
number-of-pebbles-in-row
, is unneeded!
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:
A recursive function contains code that tells itself to evaluate itself. When the function evaluates itself, it again finds the code that tells itself to evaluate itself, so the function evaluates itself again ... and again ... A recursive function will keep telling itself to evaluate itself again forever unless it is also provided with a stop condition.
A recursive function typically contains a conditional expression which has three parts:
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.
A template for a recursive function looks like this:
(defun name-of-recursive-function (argument-list) "documentation..." body... (if do-again-test (name-of-recursive-function next-step-expression)))
Each time the recursive function is evaluated, an argument is bound to the value of the next-step-expression; and that value is used in the do-again-test. 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.
while
loop with recursion.
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.
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.
(setq animals '(giraffe gazelle lion tiger)) (defun print-elements-recursively (list) "Print each element of LIST on a line of its own. Uses recursion." (print (car list)) ; body (if list ; do-again-test (print-elements-recursively ; recursive call (cdr list)))) ; next-step-expression (print-elements-recursively animals)
The print-elements-recursively
function first prints the first
element of the list, the CAR of the list. Then, if the list is
not empty, 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.
When this evaluation occurs, the function prints the first element of
the list it receives as its argument (which is the second element
of the original list). Then, the if
expression is evaluated
and when true, 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.
Each time the function invokes itself, it invokes itself on a shorter
version of the original list. Eventually, the function invokes itself
on an empty list. The print
function prints the empty list as
nil
. Next, 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
. Consequently, you
see nil
twice when you evaluate the function.
When you evaluate (print-elements-recursively animals)
in the
`*scratch*' buffer, you see this result:
giraffe gazelle lion tiger nil nil
(The first nil
is the value of the empty list that is printed;
the second nil
is the value returned by the whole function.)
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.)
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.
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:
(1- number)
so Emacs decrements the
value of number
from 2 to 1.
triangle-recursively
function.
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.
number
.
number
is the second element of the list that
starts with +
; its value is 2.
+
expression.
+
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.
Suppose that triangle-recursively
is called with an argument of
3.
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.)
triangle-recursively
function.
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.
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 with a smaller argument, until the argument is small
enough so that it does not evaluate itself.
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.
triangle
in which each row has a
value which is the square of the row number. Use a while
loop.
triangle
that multiplies instead of
adds the values.
cond
.