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
|