Common LISP Hints: Functions

## 7. Functions

You saw one example of a function above. Here are some more:

> `

>     > (+ 3 4 5 6)                   ;this function takes any number of arguments
>     18
>     > (+ (+ 3 4) (+ (+ 4 5) 6))     ;isn't prefix notation fun?
>     22
>     > (defun foo (x y) (+ x y 5))   ;defining a function
>     FOO
>     > (foo 5 0)                     ;calling a function
>     10
>     > (defun fact (x)               ;a recursive function
>         (if (> x 0)
>           (* x (fact (- x 1)))
>           1
>       ) )
>     FACT
>     > (fact 5)
>     120
>     > (defun a (x) (if (= x 0) t (b (- x))))        ;mutually recursive functions
>     A
>     > (defun b (x) (if (> x 0) (a (- x 1)) (a (+ x 1))))
>     B
>     > (a 5)
>     T
>     > (defun bar (x)                ;a function with multiple statements in
>         (setq x (* x 3))            ;its body -- it will return the value
>         (setq x (/ x 2))            ;returned by its final statement
>         (+ x 4))
>     BAR
>     > (bar 6)
>     13

> `

When we defined `foo`, we gave it two arguments, `x` and `y`. Now when we call `foo`, we are required to provide exactly two arguments: the first will become the value of `x` for the duration of the call to `foo`, and the second will become the value of `y` for the duration of the call. In LISP, most variables are lexically scoped; that is, if `foo` calls `bar` and `bar` tries to reference `x`, `bar` will not get `foo`'s value for `x`.

The process of assigning a symbol a value for the duration of some lexical scope is called binding.

You can specify optional arguments for your functions. Any argument after the symbol `&optional` is optional:

> `

>     > (defun bar (x &optional y) (if y x 0))
>     BAR
>     > (defun baaz (&optional (x 3) (z 10)) (+ x z))
>     BAAZ
>     > (bar 5)
>     0
>     > (bar 5 t)
>     5
>     > (baaz 5)
>     15
>     > (baaz 5 6)
>     11
>     > (baaz)
>     13

> `

It is legal to call the function `bar` with either one or two arguments. If it is called with one argument, `x` will be bound to the value of that argument and `y` will be bound to `nil`; if it is called with two arguments, `x` and `y` will be bound to the values of the first and second argument, respectively.

The function `baaz` has two optional arguments. It specifies a default value for each of them: if the caller specifies only one argument, `z` will be bound to 10 instead of to `nil`, and if the caller specifies no arguments, `x` will be bound to 3 and `z` to 10.

You can make your function accept any number of arguments by ending its argument list with an `&rest` parameter. LISP will collect all arguments not otherwise accounted for into a list and bind the `&rest` parameter to that list. So:

> `

>     > (defun foo (x &rest y) y)
>     FOO
>     > (foo 3)
>     NIL
>     > (foo 4 5 6)
>     (5 6)

> `

Finally, you can give your function another kind of optional argument called a keyword argument. The caller can give these arguments in any order, because they're labelled with keywords.

> `

>     > (defun foo (&key x y) (cons x y))
>     FOO
>     > (foo :x 5 :y 3)
>     (5 . 3)
>     > (foo :y 3 :x 5)
>     (5 . 3)
>     > (foo :y 3)
>     (NIL . 3)
>     > (foo)
>     (NIL)

> `

An `&key` parameter can have a default value too:

> `

>     > (defun foo (&key (x 5)) x)
>     FOO
>     > (foo :x 7)
>     7
>     > (foo)
>     5

> `