File: jcontrols.tex

package info (click to toggle)
euslisp 9.27%2Bdfsg-7
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye
  • size: 55,344 kB
  • sloc: ansic: 41,162; lisp: 3,339; makefile: 256; sh: 208; asm: 138; python: 53
file content (275 lines) | stat: -rw-r--r-- 12,960 bytes parent folder | download | duplicates (3)
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
273
274
275
\section{制御構造}
\markright{\arabic{section}. 制御構造}
\subsection{条件文}

{\bf and,or}および{\bf cond}は、Common Lispにおいてマクロとして知られているが、
EusLispではインタプリタ時の効率を改善するために特殊書式として実行される。

\begin{refdesc}
\specialdesc{and}{\&rest forms}{
{\em form}は、NILが現れるまで左から右に評価される。
もし、全ての書式がnon-NILとして評価されるならば、
最後の値が返される。}

\specialdesc{or}{\&rest forms}{
{\em form}は、non-NIL値が現れるまで左から右に評価される。
そして、その値が返される。
もし、全ての書式がNILとして評価されるならば、NILを返す。}

\specialdesc{if}{test then \&optional else}{
{\bf if}は、1つの{\it then}と{\it else}書式のみを持つことができる。
そこに多重書式を書きたいときは、{\bf progn}を使って
グループ化しなければならない。}

\macrodesc{when}{test \&rest forms}{
{\bf if}と違って、
{\bf when}と{\bf unless}は、多重{\em 書式}で書くことを許可している。
{\em test}の評価がnon-NILのとき、{\bf when}は実行され、
評価がNILのとき、{\em unless}は実行される。
もう一方で、これらのマクロは{\em else}書式を追加することを
許可していない。}

\macrodesc{unless}{test \&rest forms}{
{\tt(when (not {\em test}) . {\em forms})}と同等である。}

\specialdesc{cond}{\&rest (test \&rest forms)}{
任意の数の条件項は、{\bf cond}の後に続けることができる。
それぞれの条件項において、最初の書式{\em test}が評価される。
もし、non-NILであったとき、その条件項の残りの書式は、続いて評価される。
そして、最後の値が返される。
もし、{\em test}のあとに書式がなかったならば、
{\em test}の値が返される。
{\em test}が失敗したとき、次の条件項は{\em test}がnon-NIL評価されるかまたは
全ての条件項が尽きてしまうまで繰り返される。
条件項が尽きてしまった場合、{\bf cond}はNILを返す。}

\macrodesc{case}{key \&rest (label \&rest forms)}{
{\em key}と{\em label}が一致した条件項について、
{\em form}が評価され、最後の値が返される。
{\em key}と{\em label}の間の等価は、{\bf eq}または
{\bf memq}で行われ、{\bf equal}ではない。}

\end{refdesc}

\subsection{逐次実行とLet}

\begin{refdesc}
\funcdesc{prog1}{form1 \&rest forms}{
{\em form1}と{\em forms}は、次々と評価され、
{\em form1}から返される値が{\bf prog1}の値として返される。}

\specialdesc{progn}{\&rest forms}{
{\em form}は次々に評価され、最後の{\em form}の値が返される。
{\bf progn}は特殊書式である。なぜなら、ファイルの最初に現れたとき
特別な意味を持つからである。
そのような書式がコンパイルされたとき、内部書式はすべて最初に現れた
として見なす。
マクロが{\bf defun}や{\bf defmethod}の連続で拡張される場合、それが最初に
現われなければならないときに役立つ。}

\macrodesc{setf}{\&rest forms}{
{\em forms}中の各formにおいて、第二要素を一般化変数である第一要素に割り当てる。}

\specialdesc{let}{(\&rest (var \&optional value)) \&rest forms}{
ローカル変数を生成する。
すべての{\em value}は評価され、並行して{\em var}に割り当てられる。すなわち、
{\tt (let ((a 1)) (let ((a (1+ a)) (b a)) (list a b)))} の結果は
(2 1)である。}

\specialdesc{let*}{(\&rest (var \&optional value)) \&rest forms}{
ローカル変数を生成する。
全ての{\em value}は次々に評価され、{\em var}に割り当てられる。すなわち、
{\tt (let ((a 1)) (let* ((a (1+ a)) (b a)) (list a b)))}の結果は
(2 2)である。}
\end{refdesc}

\subsection{ローカル関数}
\begin{refdesc}
\specialdesc{flet}{(\&rest (fname lambda-list \&rest body)) \&rest forms}{
ローカル関数を定義する。}

\specialdesc{labels}{(\&rest (fname lambda-list \&rest body)) \&rest forms}{
ローカルなスコープとなる関数を定義する。
{\bf flet}と{\bf labels}との違いは、
{\bf flet}で定義されたローカル関数は、その他の関数を参照または再帰できないが、
{\bf labels}は相互の参照を許可する。}

\end{refdesc}

\subsection{ブロックとExit}
\begin{refdesc}
\specialdesc{block}{tag \&rest forms}{
{\bf return-from}によって脱出可能なローカルブロックを作る。
{\em tag}は、ローカルにスコープされ、評価されない。}

\specialdesc{return-from}{tag \&optional value}{
{\em tag}によって示されたブロックを脱出する。
{\bf return-from}は、関数やメソッドから脱出するときに使用される。
関数やメソッドは、その本体をすべて取り囲んだ部分をブロックとして
自動的に確定され、その関数またはメソッドの名前を付ける。}

\macrodesc{return}{\&optional value}{
{\tt  (return x)}は、{\tt (return-from nil x)}と同等である。
{\bf loop, while, do, dolist, dotimes}は、暗黙的にNILと名前が付けられた
ブロックとして確定されるため、これらの特殊書式と組み合わせて使用する。}

\specialdesc{catch}{tag \&rest forms}{
{\bf throw}によって脱出または値を返すための動的なブロックを確定する。
{\em tag}は評価される。

全て見える{\bf catch}の{\em tag}は、{\tt sys:list-all-catchers}から得ることができる。}

\specialdesc{throw}{tag value}{
{\bf catch}ブロックから脱出または{\em value}を返す。
{\em tag}と{\em value}は評価される。}

\specialdesc{unwind-protect}{protected-form \&rest cleanup-forms}{
{\em protected-form}の評価が終った後、
{\em cleanup-form}が評価される。
{\bf unwind-protect}の外側にブロックまたは{\bf catch}
ブロックを作っても構わない。

{\bf return-from}や{\bf throw}でさえ、そのようなブロックから
抜け出すためには{\em protected-form}の中で実行される。
{\em cleanup-form}は、評価されることが保証されている。
また、もし{\em protected-form}が実行されている間にエラーが起こったならば、
{\em cleanup-form}はいつも{\bf reset}によって実行される。}

\end{refdesc}

\subsection{繰返し}

\begin{refdesc}

\specialdesc{while}{test \&rest forms}{
{\em test}がnon-NILと評価されている間、
{\em form}は、繰返し評価される。
{\bf while}は、{\em form}のまわりにNILと名付けられるブロックを自動的に確定する
特殊書式である。
{\bf return}は、そのループから抜け出すために使用することができる。
次のイテレーションへ飛ぶときためには後に紹介する{\bf tagbody}と{\bf go}を次のように使う:}

\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}{
{\em tag}は、{\bf go}のために名付けられる。
{\bf tagbody}の中のみ{\bf go}を使用することができる。}

\specialdesc{go}{tag}{
ローカルにスコープされた{\bf tagbody}のなかに現れる{\em tag}の直後の
書式に制御を移す。
ローカルスコープを横切って違う{\bf tagbody}のtagに制御を移すことは
禁止されている。}

\macrodesc{prog}{varlist \&rest tag-or-statement}{
{\bf prog}はマクロで、以下のように展開される。
\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}はローカル変数である。
それぞれの{\em var}に、{\em init}は並行に評価され、割り当てられる。
つぎに、{\em endtest}が評価され、もし真のとき{\bf do}は{\em result}を返す。
 (そうでないときは、NILを返す)
もし{\em endtest}がNILを返したならば、それぞれの{\em form}は、
順番に評価される。
書式の評価後、{\em next}が評価され、その値は
それぞれの{\em var}に再割当され、次の繰返しが始まる。}

\macrodesc{do*}{(\&rest (var \&optional optional init next)) (endtest \&optional result) \&rest forms}{
{\bf do*}は、{\em init}と{\em next}の評価と
{\em var}への割り当てが連続的に起こることを除いて、{\bf do}と同様である。}

\macrodesc{dotimes}{(var count \&optional result) \&rest forms}{
{\em forms}の評価を{\em count}回行う。
{\em count}は、一回のみ評価される。
それぞれの評価の中で、{\em var}は整数のゼロから
{\em count}-1まで増加する。}

\macrodesc{dolist}{(var list \&optional result) \&rest forms}{
{\em list}のそれぞれの要素は、{\em var}に連続的に与えられる。
そして{\em forms}は、それぞれの値で評価される。
{\bf dolist}は、他の繰返しより早く実行される。たとえば、
{\bf mapcar}や再帰的関数のようなものより。
それは、{\bf dolist}が関数のclosureを作ったり適用したりする必要が
なく、新しいパラメータのバインドが必要でないため。}

\macrodesc{until}{condition \&rest forms}{
{\em condition}が満たされている間、{\em forms}を評価する。}

\macrodesc{loop}{\&rest forms}{
{\em forms}を永遠に評価する。
実行を止めるためには、{\bf return-from, throw}または{\bf go}が
{\em forms}のなかで評価されなければならない。}

\subsection{述語}

Common Lispの{\bf typep}と{\bf subtypep}はないので、
{\bf subclassp}や{\bf derivedp}で疑似実現すること。

\begin{refdesc}

\funcdesc{eq}{obj1 obj2}{
{\em obj1}と{\em obj2}が同じオブジェクトを指すポインタ
あるいは同じ数値のときTを返す。
例えば:{\tt (eq 'a 'a)}はT、{\tt (eq 1 1)}はT、{\tt (eq 1. 1.0)}はNIL、
{\tt (eq "a" "a")}はNILである。}
\funcdesc{eql}{obj1 obj2}{
EusLispの中で数値は全て直接値で表現されるため、{\bf eq}と{\bf eql}は
同一である。}
\funcdesc{equal}{obj1 obj2}{
いろんな構造のオブジェクトの等価性をチェックする。オブジェクトは、文字列・ベクトル・
行列などで再帰的に参照してないことが保証されなければならない。
{\em obj1}や{\em obj2}が再帰的に参照されていたとすると、
{\bf equal}は無限ループとなる。}
\funcdesc{superequal}{obj1 obj2}{
{\bf superequal}は、環状参照をチェックするので遅い。しかしロバストな等価が得られる。}

\funcdesc{null}{object}{
{\em object}がNILのとき、Tを返す。
{\tt (eq {\em object} nil)}を評価する。}
\funcdesc{not}{object}{
{\bf not}は、{\bf null}と同一である。}
\funcdesc{atom}{object}{
オブジェクトがconsのインスタンスである時のみ、NILを返す。
{\tt (atom nil) = (atom '()) = T)}\\
注意:vectors, strings, read-table, hash-tableなどに対しては、それらがどんなに
複雑なオブジェクトとなっていても{\bf atom}はTを返す。}
\funcdesc{every}{pred \&rest args}{
全ての{\em args}が{\em pred}についてTを返した時のみ
Tを返す。{\bf every}は、{\em pred}が全ての{\em args}に対して効力があるかどうかを
検査する時に使用される。}
\funcdesc{some}{pred \&rest args}{
{\em args}のうちどれか1つが{\em pred}についてTを返したとき
Tを返す。{\bf some}は、{\em pred}が{\em args}のどれかに対して効力があるかどうかを
検査する時に使用される。}
\end{refdesc}
\funcdesc{functionp}{object}{
{\em object}が{\bf apply}や{\bf funcall}で与えられる関数オブジェクトであるならTを返す。\\
注意:マクロは{\bf apply}や{\bf funcall}を適用することができない。
{\bf functionp}は、{\em object}が、type=0のコンパイルコードか、関数定義を持つsymbolか、
lambda-formかあるいはlambda-closureであったとき、Tを返す。
{\tt Examples: (functionp 'car) = T, (functionp 'do) = NIL}}
\funcdesc{compiled-function-p}{object}{
{\em object}が、コンパイルコードのインスタンスであったとき、Tを返す。
そのコンパイルコードが関数かまたはマクロかを知るためには、
そのオブジェクトに{\tt :type}メッセージを送り、その返り値が
{\tt function}と{\tt macro}のどちらになっているかを調べる。}

\end{refdesc}

\newpage