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:

λ-syntaxCombined `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)`

#### Implementation

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;
.
.
.
}
```

#### Testing

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 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.