File: LISP-tutorial-7.html

package info (click to toggle)
cmucl 20c-2
  • links: PTS
  • area: main
  • in suites: wheezy
  • size: 42,524 kB
  • sloc: lisp: 358,331; ansic: 28,385; asm: 3,777; sh: 1,236; makefile: 366; csh: 31
file content (147 lines) | stat: -rw-r--r-- 4,334 bytes parent folder | download | duplicates (12)
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>
&gt; (+ 3 4 5 6)                   ;this function takes any number of arguments
18
&gt; (+ (+ 3 4) (+ (+ 4 5) 6))     ;isn't prefix notation fun?
22
&gt; (defun foo (x y) (+ x y 5))   ;defining a function
FOO
&gt; (foo 5 0)                     ;calling a function
10
&gt; (defun fact (x)               ;a recursive function
    (if (&gt; x 0) 
      (* x (fact (- x 1)))
      1
  ) )
FACT
&gt; (fact 5)
120
&gt; (defun a (x) (if (= x 0) t (b (- x))))        ;mutually recursive functions
A
&gt; (defun b (x) (if (&gt; x 0) (a (- x 1)) (a (+ x 1))))
B
&gt; (a 5)
T
&gt; (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
&gt; (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>&amp;optional</CODE> is optional:</P>
<P>
<BLOCKQUOTE><CODE>
<PRE>
&gt; (defun bar (x &amp;optional y) (if y x 0))
BAR
&gt; (defun baaz (&amp;optional (x 3) (z 10)) (+ x z))
BAAZ
&gt; (bar 5)
0
&gt; (bar 5 t)
5
&gt; (baaz 5)
15
&gt; (baaz 5 6)
11
&gt; (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>&amp;rest</CODE> parameter. LISP will collect all arguments
not otherwise accounted for into a list and bind the <CODE>&amp;rest</CODE>
parameter to 
that list. So:</P>
<P>
<BLOCKQUOTE><CODE>
<PRE>
&gt; (defun foo (x &amp;rest y) y)
FOO
&gt; (foo 3)
NIL
&gt; (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>
&gt; (defun foo (&amp;key x y) (cons x y))
FOO
&gt; (foo :x 5 :y 3)
(5 . 3)
&gt; (foo :y 3 :x 5)
(5 . 3)
&gt; (foo :y 3)
(NIL . 3)
&gt; (foo)
(NIL)
</PRE>
</CODE></BLOCKQUOTE>
</P>
<P>An <CODE>&amp;key</CODE> parameter can have a default value too:</P>
<P>
<BLOCKQUOTE><CODE>
<PRE>
&gt; (defun foo (&amp;key (x 5)) x)
FOO
&gt; (foo :x 7)
7
&gt; (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>