Rest Parameters
Optional parameters are just the thing when you have discrete parameters for which the caller may or may not want to provide values. But some functions need to take a variable number of arguments. Several of the built-in functions you’ve seen already work this way. **FORMAT**
has two required arguments, the stream and the control string. But after that it needs a variable number of arguments depending on how many values need to be interpolated into the control string. The **+**
function also takes a variable number of arguments—there’s no particular reason to limit it to summing just two numbers; it will sum any number of values. (It even works with zero arguments, returning 0, the identity under addition.) The following are all legal calls of those two functions:
(format t "hello, world")
(format t "hello, ~a" name)
(format t "x: ~d y: ~d" x y)
(+)
(+ 1)
(+ 1 2)
(+ 1 2 3)
Obviously, you could write functions taking a variable number of arguments by simply giving them a lot of optional parameters. But that would be incredibly painful—just writing the parameter list would be bad enough, and that doesn’t get into dealing with all the parameters in the body of the function. To do it properly, you’d have to have as many optional parameters as the number of arguments that can legally be passed in a function call. This number is implementation dependent but guaranteed to be at least 50. And in current implementations it ranges from 4,096 to 536,870,911.6 Blech. That kind of mind-bending tedium is definitely not The Lisp Way.
Instead, Lisp lets you include a catchall parameter after the symbol **&rest**
. If a function includes a **&rest**
parameter, any arguments remaining after values have been doled out to all the required and optional parameters are gathered up into a list that becomes the value of the **&rest**
parameter. Thus, the parameter lists for **FORMAT**
and **+**
probably look something like this:
(defun format (stream string &rest values) ...)
(defun + (&rest numbers) ...)