1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
<HTML>
<HEAD>
<TITLE>Common LISP Hints: Functions</TITLE>
</HEAD>
<BODY>
<A HREF="LISP-tutorial-6.html"><IMG SRC="prev.gif" ALT="Previous"></A>
<A HREF="LISP-tutorial-8.html"><IMG SRC="next.gif" ALT="Next"></A>
<A HREF="LISP-tutorial.html#toc7"><IMG SRC="toc.gif" ALT="Contents"></A>
<HR>
<H2><A NAME="s7">7. Functions</A></H2>
<P>You saw one example of a function above. Here are some more:</P>
<P>
<BLOCKQUOTE><CODE>
<PRE>
> (+ 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
</PRE>
</CODE></BLOCKQUOTE>
</P>
<P>When we defined <CODE>foo</CODE>, we gave it two arguments, <CODE>x</CODE> and
<CODE>y</CODE>. Now when we
call <CODE>foo</CODE>, we are required to provide exactly two arguments: the first
will become the value of <CODE>x</CODE> for the duration of the call to
<CODE>foo</CODE>, and the
second will become the value of <CODE>y</CODE> for the duration of the call. In
LISP, most variables are lexically scoped; that is, if <CODE>foo</CODE> calls <CODE>bar</CODE>
and <CODE>bar</CODE> tries to reference <CODE>x</CODE>, <CODE>bar</CODE> will not get
<CODE>foo</CODE>'s value for <CODE>x</CODE>. </P>
<P>The process of assigning a symbol a value for the duration of some
lexical scope is called binding.</P>
<P>You can specify optional arguments for your functions. Any argument
after the symbol <CODE>&optional</CODE> is optional:</P>
<P>
<BLOCKQUOTE><CODE>
<PRE>
> (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
</PRE>
</CODE></BLOCKQUOTE>
</P>
<P>It is legal to call the function <CODE>bar</CODE> with either one or two arguments.
If it is called with one argument, <CODE>x</CODE> will be bound to the value of that
argument and <CODE>y</CODE> will be bound to <CODE>nil</CODE>; if it is called with two
arguments, <CODE>x</CODE> and <CODE>y</CODE> will be bound to the values of the first
and second
argument, respectively.</P>
<P>The function <CODE>baaz</CODE> has two optional arguments. It specifies a default
value for each of them: if the caller specifies only one argument, <CODE>z</CODE>
will be bound to 10 instead of to <CODE>nil</CODE>, and if the caller specifies no
arguments, <CODE>x</CODE> will be bound to 3 and <CODE>z</CODE> to 10.</P>
<P>You can make your function accept any number of arguments by ending its
argument list with an <CODE>&rest</CODE> parameter. LISP will collect all arguments
not otherwise accounted for into a list and bind the <CODE>&rest</CODE>
parameter to
that list. So:</P>
<P>
<BLOCKQUOTE><CODE>
<PRE>
> (defun foo (x &rest y) y)
FOO
> (foo 3)
NIL
> (foo 4 5 6)
(5 6)
</PRE>
</CODE></BLOCKQUOTE>
</P>
<P>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.</P>
<P>
<BLOCKQUOTE><CODE>
<PRE>
> (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)
</PRE>
</CODE></BLOCKQUOTE>
</P>
<P>An <CODE>&key</CODE> parameter can have a default value too:</P>
<P>
<BLOCKQUOTE><CODE>
<PRE>
> (defun foo (&key (x 5)) x)
FOO
> (foo :x 7)
7
> (foo)
5
</PRE>
</CODE></BLOCKQUOTE>
</P>
<HR>
<A HREF="LISP-tutorial-6.html"><IMG SRC="prev.gif" ALT="Previous"></A>
<A HREF="LISP-tutorial-8.html"><IMG SRC="next.gif" ALT="Next"></A>
<A HREF="LISP-tutorial.html#toc7"><IMG SRC="toc.gif" ALT="Contents"></A>
</BODY>
</HTML>
|