Previous | Table of Contents | Next |
The while special form tests whether the value returned by evaluating its first argument is true or false. If true, the Lisp interpreter evaluates the remaining arguments of the expression and then again tests whether the first argument to while is true or false. If false, the Lisp interpreter skips the rest of the expression (the body of the expression) and does not evaluate it.
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 because the Lisp interpreter repeats the same thing again and again.
The value returned by evaluating a while is the value of true-or-false-test. Consequently, a while loop that evaluates without error returns 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! This means that a while loop is always evaluated for its side effects.
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.
Here is an example of a while loop:
(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))))
The while loop is the body of a function that prints the elements of a list, one after another, each on a line of its own.
The first four parts of the function definition are the special form defun, the name of the function, print-elements-of-list, the argument list, with one local variable called list, and the documentation string.
The body of the function definition consists of a while loop.
The test for the while loop consists of just the local variable, list. When the while expression is evaluated, the Lisp interpreter first evaluates the variable list. If the list is empty, it returns an empty list, (), which is nil, or false. But if the list is not empty, it returns a non-nil value, which is understood by the Lisp interpreter as true. Hence, the test part of this while loop tests true so long as the list has elements.
The second argument of the while loop (which is the first element of its body) is the expression
(print (car list))
This expression consists of the function print, whose intended action is self-explanatory, and the expression (car list), which is not self-explanatory.
To understand car and its sibling, cdr, it is necessary to take a short detour. This is worth doing since car and cdr (and a third function, cons) are fundamental to Lisp.
In Lisp, car, cdr, and cons are fundamental functions. The cons function is used to construct lists, and the car and cdr functions are used to take them apart: car returns the first element of a list, and cdr returns the rest of the list.
The name of the cons function is not unreasonable: It is an abbreviation of the word construct. The origins of the names for car and cdr, on the other hand, are esoteric: car is an acronym from the phrase contents of the address part of the register; and cdr (pronounced could-er) is an acronym from the phrase contents of the decrement part of the register. These phrases refer to specific pieces of hardware on the very early computer on which the original Lisp was developed. Besides being obsolete, the phrases have been completely irrelevant for more than 30 years to anyone thinking about Lisp. Nonetheless, although a few brave scholars have begun to use more reasonable names for these functions, such as first and rest, the old terms are still in use. Because the terms are used in the Emacs Lisp source code, we will use them also.
The car of a list is, quite simply, the first item in the list. Thus the car of the list (rose violet daisy buttercup) is rose. Here is an example:
(car (rose violet daisy buttercup)) → rose
The cdr of a list is the rest of the list, that is, the cdr function returns the part of the list that follows the first item:
(cdr (rose violet daisy buttercup)) → (violet daisy buttercup)
As mentioned previously, car returns the first element of a list, and cdr returns the rest of the list.
cons (which I mention here for completeness) is used to construct lists (that car and cdr can take apart).Here are three examples of cons expressions:
(cons maple ()) → (maple) (cons oak (maple)) → (oak maple) (cons pine (oak maple)) → (pine oak maple)
Starting with an empty list, (), in each example, one element is added, or more precisely, prepended, to the list. The first cons expression returns the one element list (maple); the second cons expression returns the two-element list (oak maple); and the third cons expression returns the three-element list (pine oak maple).
Previous | Table of Contents | Next |