/
controls.tex
272 lines (227 loc) · 10.4 KB
/
controls.tex
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
\section{Control Structures}
\markright{\arabic{section}. Control Structures}
\subsection{Conditionals}
Although {\bf and, or} and {\bf cond} are advised to be macros by Common Lisp,
they are implemented as special forms in EusLisp to improve
the interpreting performance.
\begin{refdesc}
\specialdesc{and}{\&rest forms}{
{\em Form}s are evaluated from left to right until NIL appears.
If all forms are evaluated to non-NIL, the last value is returned.}
\specialdesc{or}{\&rest forms}{
{\em Form}s are evaluated from left to right until non-NIL appears,
and the value is returned. If all forms are evaluated to NIL,
NIL is returned.}
\specialdesc{if}{test then \&optional else}{
{\bf if} can only have single {\it then} and {\it else} forms.
To allow multiple {\em then} or {\em else} forms,
they must be grouped by {\bf progn}.}
\macrodesc{when}{test \&rest forms}{
Unlike {\bf if},
{\bf when} and {\bf unless} allow you to write multiple {\em forms}
which are executed when {\em test} holds ({\bf when}) or
does not {\em unless}.
On the other hand, these macros
cannot have the {\em else} forms.}
\macrodesc{unless}{test \&rest forms}{
is equivalent to {\tt(when (not {\em test}) . {\em forms})}.}
\specialdesc{cond}{\&rest (test \&rest forms)}{
Arbitrary number of cond-clauses can follow {\bf cond}.
In each clause, the first form, that is {\em test}, is evaluated.
If it is non-nil, the rest of the forms in that clause are evaluated sequentially,
and the last value is returned.
If no forms are given after the {\em test}, the value of the {\em test} is returned.
When the {\em test} fails, next clause is tried until a {\em test} which is evaluated
to non-nil is found or all clauses are exhausted.
In the latter case, {\bf cond} returns NIL.}
\macrodesc{case}{key \&rest (label \&rest forms)}{
For the clause whose {\em label} matches with {\em key},
{\em form}s are evaluated and the last value is returned.
Equality between {\em key} and {\em label} is tested with {\bf eq}
or {\bf memq}, not with {\bf equal}.}
\end{refdesc}
\subsection{Sequencing and Lets}
\begin{refdesc}
\funcdesc{prog1}{form1 \&rest forms}{
{\em form1} and {\em forms} are evaluated sequentially,
and the value returned by {\em form1} is returned as the value of {\bf prog1}.}
\specialdesc{progn}{\&rest forms}{
{\em Form}s are evaluated sequentially, and the value of the rightmost form
is returned.
{\bf Progn} is a special form because it has a special meaning when it
appeared at top level in a file.
When such a form is compiled, all inner forms are regarded as they appear
at top level.
This is useful for a macro which expands to a series of
{\bf defun}s or {\bf defmethod}s, which must appear at top level.}
\macrodesc{setf}{\&rest forms}{
for each form in {\em forms}, assigns the second element to the generalized-variable signilized by the first element.}
\specialdesc{let}{(\&rest (var \&optional value)) \&rest forms}{
introduces local variables.
All {\em value}s are evaluated and assigned to {\em var}s in parallel, i.e.,
{\tt (let ((a 1)) (let ((a (1+ a)) (b a)) (list a b)))} produces
(2 1).
The first statements of {\em forms} can be declarations.}
\specialdesc{let*}{(\&rest (var \&optional value)) \&rest forms}{
introduces local variables.
All {\em value}s are evaluated sequentially, and assigned to {\em var}s
i.e.,
{\tt (let ((a 1)) (let* ((a (1+ a)) (b a)) (list a b)))} produces
(2 2).}
\end{refdesc}
\subsection{Local Functions}
\begin{refdesc}
\specialdesc{flet}{(\&rest (fname lambda-list \&rest body)) \&rest forms}{
defines local functions.}
\specialdesc{labels}{(\&rest (fname lambda-list \&rest body)) \&rest forms}{
defines locally scoped functions.
The difference between {\em flet} and {\em labels} is,
the local functions defined by {\em flet} cannot reference
each other or recursively, whereas {\em labels} allows such mutual references.}
\end{refdesc}
\subsection{Blocks and Exits}
\begin{refdesc}
\specialdesc{block}{tag \&rest forms}{
makes a lexical block from which you can exit by {\bf return-from}.
{\em Tag} is lexically scoped and is not evaluated.}
\specialdesc{return-from}{tag \&optional value}{
exits the block labeled by {\em tag}.
{\bf return-from} can be used to exit from a function or a method which
automatically establishes block labeled by its function or method name
surrounding the entire body.}
\macrodesc{return}{\&optional value}{
{\tt (return x)} is equivalent to {\tt (return-from nil x)}. This is
convenient to use in conjunction with {\bf loop, while, do, dolist,}
and {\bf dotimes} which implicitly establish blocks labeled NIL.}
\specialdesc{catch}{tag \&rest forms}{
establishes a dynamic block from which you can exit and return a value
by {\bf throw}. {\em Tag} is evaluated.
The list of all visible catch tags can be obtained by {\tt
sys:list-all-catchers}.}
\specialdesc{throw}{tag value}{
exits and returns {\em value} from a catch block.
{\em tag} and {\em value} are evaluated.}
\specialdesc{unwind-protect}{protected-form \&rest cleanup-forms}{
After the evaluation of {\em protected-form} finishes,
{\em cleanup-form} is evaluated.
You may make a block or a catch block outside the {\tt unwind-protect}.
Even {\bf return-from} or {\bf throw} is executed in {\em protected-form}
to escape from such blocks, {\em cleanup-forms} are assured to be evaluated.
Also, if you had an error while executing {\em protected-form},
{\em cleanup-form} would always be executed by {\em reset}.}
\end{refdesc}
\subsection{Iteration}
\begin{refdesc}
\specialdesc{while}{test \&rest forms}{
While {\em test} is evaluated to non-nil,
{\em form}s are evaluated repeatedly.
{\bf While} special form automatically establishes a block by name of nil
around {\em form}s, and {\bf return} can be used to exit from the loop.
To jump to next iteration, you can use following syntax with {\bf tagbody} and {\bf go} described below:}
\begin{verbatim}
(setq cnt 0)
(while
(< cnt 10)
(tagbody while-top
(incf cnt)
(when (eq (mod cnt 3) 0)
(go while-top)) ;; jump to next iteraction
(print cnt)
)) ;; 1, 2, 4, 5, 7, 8, 10
\end{verbatim}
\specialdesc{tagbody}{\&rest tag-or-statement}{
tags can be used as labels for {\bf go}.
You can use {\bf go} only in {\bf tagbody}.}
\specialdesc{go}{tag}{
transfers control to the form just after {\em tag}
which appears in a lexically scoped {\bf tagbody}.
{\bf Go} to the tag in a different {\bf tagbody}
across the lexical scope is inhibited.}
\macrodesc{prog}{varlist \&rest tag-or-statement}{
{\bf prog} is a macro, which expands as follows:
\ptext{
(block nil
(let {\em varlist}
(tagbody
{\em tag-or-statement})))}
}
\macrodesc{do}{(\&rest (var \&optional optional init next)) (endtest \&optional result) \&rest forms}{
{\em var}s are local variables.
To each {\em var}, {\em init} is evaluated in parallel and assigned.
Next, {\em endtest} is evaluated and if it is true, {\bf do} returns
{\em result} (defaulted to NIL).
If {\em endtest} returns NIL, each {\em form} is evaluated sequentially.
After the evaluation of forms, {\em next} is evaluated and the value is
reassigned to each {\em var}, and the next iteration starts.}
\macrodesc{do*}{(\&rest (var \&optional optional init next)) (endtest \&optional result) \&rest forms}{
{\bf do*} is same as {\bf do} except that the evaluation of {\em init}
and {\em next}, and their assignment to {\em var} occur sequentially.}
\macrodesc{dotimes}{(var count \&optional result) \&rest forms}{
evaluates {\em forms} {\em count} times.
{\em count} is evaluated only once.
In each evaluation, {\em var} increments from integer zero to
{\em count} minus one.}
\macrodesc{dolist}{(var list \&optional result) \&rest forms}{
Each element of {\em list} is sequentially bound to {\em var},
and {\em forms} are evaluated for each binding.
{\bf Dolist} runs faster than other iteration constructs
such as {\bf mapcar} and recursive functions,
since {\bf dolist} does not have to create a function closure or to apply it,
and no new parameter binding is needed.}
\macrodesc{until}{condition \&rest forms}{
evaluates forms until {\em condition} holds.}
\macrodesc{loop}{\&rest forms}{
evaluates {\em forms} forever.
To terminate execution, {\bf return-from, throw} or {\bf go} needed to be
evaluated in {\em forms}.}
\subsection{Predicates}
{\bf Typep} and {\bf subtypep} of Common Lisp are not provided, and should be
simulated by {\bf subclassp} and {\bf derivedp}.
\begin{refdesc}
\funcdesc{eq}{obj1 obj2}{
returns T if {\em obj1} and {\em obj2} are pointers to the same object
or the same numbers.
Examples: {\tt (eq 'a 'a)} is T, {\tt (eq 1 1)} is T,
{\tt (eq 1. 1.0)} is nil, {\tt (eq "a" "a")} is nil.}
\funcdesc{eql}{obj1 obj2}{
{\bf Eq} and {\bf eql} are identical since all the numbers in EusLisp are represented as
immediate values.}
\funcdesc{equal}{obj1 obj2}{
Checks the equality of any structured objects, such as strings, vectors or
matrices, as long as they do not have recursive references.
If there is recursive reference in {\em obj1} or {\em obj2},
{\bf equal} loops infinitely.}
\funcdesc{superequal}{obj1 obj2}{
Slow but robust {\bf equal}, since {\bf superequal} checks circular reference.}
\funcdesc{null}{object}{
T if {\em object} is nil.
Equivalent to (eq {\em object} nil).}
\funcdesc{not}{object}{
{\bf not} is identical to {\bf null}.}
\funcdesc{atom}{object}{
returns NIL only if object is a cons.
{\tt (atom nil) = (atom '()) = T)}.
Note that {\bf atom} returns T for vectors, strings, read-table, hash-table,
etc., no matter what complex objects they are.}
\funcdesc{every}{pred \&rest args}{
returns T if all {\em args} return T for {\em pred}.
{\bf Every} is used to test whether {\em pred} holds for every {\em args}.}
\funcdesc{some}{pred \&rest args}{
returns T if at least one of {\em args} return T for {\em pred}.
{\bf Some} is used to test whether {\em pred} holds for any of {\em args}.}
\end{refdesc}
\funcdesc{functionp}{object}{
T if {\em object} is a function object that can be given to
{\bf apply} and {\bf funcall}.
Note that macros cannot be {\em apply}'ed or {\em funcall}'ed.
{\bf Functionp} returns T, if {\em object} is
either a compiled-code with type=0, a symbol that has function definition,
a lambda-form, or a lambda-closure.
Examples: (functionp 'car) = T, (functionp 'do) = NIL}
\funcdesc{compiled-function-p}{object}{
T if {\em object} is an instance of compiled-code.
In order to know the compiled-code is a function or a macro,
send {\tt :type} message to the object, and {\tt function} or {\tt macro}
is returned.}
\end{refdesc}
\newpage