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