Up till now all functions have had a specified number of named arguments. We will now introduce a syntax for defining variadic functions, which may take a fixed number of named arguments and a variable number of additional arguments which are collected into a named list.
The argument declarations for variadic functions are improper lists:
| λ-syntax | Combined DEFINE | |
|---|---|---|
| 3 args | (LAMBDA (arg1 arg2 arg3) body...) | (DEFINE (name arg1 arg2 arg3) body...) | 
| ≥2 args | (LAMBDA (arg1 arg2 . rest) body...) | (DEFINE (name arg1 arg2 . rest) body...) | 
| ≥1 args | (LAMBDA (arg1 . rest) body...) | (DEFINE (name arg1 . rest) body...) | 
| ≥0 args | (LAMBDA args body...) | (DEFINE (name . args) body...) | 
In the definitions above, the parameters are bound as follows:
| Definition | (f 1 2 3) | ||
|---|---|---|---|
| Value of a | Value of b | Value of c | |
| (DEFINE (f a b c) body...) | 1 | 2 | 3 | 
| (DEFINE (f a b . c) body...) | 1 | 2 | (3) | 
| (DEFINE (f a . b) body...) | 1 | (2 3) | |
| (DEFINE (f . a) body...) | (1 2 3) | ||
All that is required is a small modification to
make_closure to accept the declaration:
int make_closure(Atom env, Atom args, Atom body, Atom *result)
{
	Atom p;
	if (!listp(body))
		return Error_Syntax;
	/* Check argument names are all symbols */
	p = args;
	while (!nilp(p)) {
		if (p.type == AtomType_Symbol)
			break;
		else if (p.type != AtomType_Pair
				|| car(p).type != AtomType_Symbol)
			return Error_Type;
		p = cdr(p);
	}
	*result = cons(env, cons(args, body));
	result->type = AtomType_Closure;
	return Error_OK;
}
And another to apply to bind the additional arguments
into a list:
int apply(Atom fn, Atom args, Atom *result)
{
	.
	.
	.
	/* Bind the arguments */
	while (!nilp(arg_names)) {
		if (arg_names.type == AtomType_Symbol) {
			env_set(env, arg_names, args);
			args = nil;
			break;
		}
		if (nilp(args))
			return Error_Args;
		env_set(env, car(arg_names), car(args));
		arg_names = cdr(arg_names);
		args = cdr(args);
	}
	if (!nilp(args))
		return Error_Args;
	.
	.
	.
}
A boring example:
> ((lambda (a . b) a) 1 2 3) 1 > ((lambda (a . b) b) 1 2 3) (2 3) > ((lambda args args) 1 2 3) (1 2 3)
We can also create a variadic adder:
> (define (sum-list xs)
    (if xs
        (+ (car xs) (sum-list (cdr xs)))
        0))
SUM-LIST
> (sum-list '(1 2 3))
6
> (define (add . xs) (sum-list xs))
ADD
> (add 1 2 3)
6
> (add 1 (- 4 2) (/ 9 3))
6
Since you can always pass a list to a regular function, this is really just another kind of syntactic sugar.