この規格ページの目次
31
X 3012 : 1998 (ISO/IEC 13816 : 1997)
((y) emivowel)
(t consonant)) ⇒ consonant
(let ((char #\u))
(case char
( (#\a #\i #\u #\e #\o) owels)
(t consonants))) ⇒ vowels
(case-using #= (+ 1.0 1.0)
((1) ne)
((2) wo)
(t more)) ⇒ two
(case-using #string= "bar"
(("foo") 1)
(("bar") 2)) ⇒2
6.5 評価形式の逐次実行
(progn form*) →<object> 特殊演算子
progn形式は,form*を順に評価し,その最後の評価形式の評価結果を返す。すべてのformが,左から右
に順に評価される。最後の評価形式以外のすべてのformの値は,破棄される。したがって,それらの評価
形式は,副作用のためだけに実行される。formをもたないprognは,nilを返す。
例 (defglobal x 0) ⇒x
(progn
(setq x 5)
(+ x 1)) ⇒6
(progn
(format (standard-output) "4 plus 1 equals")
(format (standard-output) "~D" (+ 4 1)))
⇒nil
これは,4 plus 1 equals 5を印字する。
6.6 繰返し
(while test-form body-form*) →<null> 特殊演算子
while形式は,test-formが真を返す間,body-form*の実行を繰り返す。詳細を次に示す。
a) est-formを評価する。その値をVtとする。
b) tがnilであれば,while形式は直ちにnilを返す。
c) tがnil以外の値であれば,一連の評価形式body-form*を左から右に順に評価する。
d) ody-form*の評価が正常に終了した場合,while形式は再びa)から実行する。
例 (let ((x ()) (i 5))
――――― [JIS X 3012 pdf 36] ―――――
32
X 3012 : 1998 (ISO/IEC 13816 : 1997)
(while (> i0) (setq x (cons i x)) (setq i(- i 1)))
x) ⇒ (1 2 3 4 5)
(for (iteration-spec*) (end-test result*) orm*) →<object> 特殊演算子
ここで,
iteration-spec ::= (var init [step])
for形式は,本体と呼ばれる評価形式の並びform*を繰り返し実行する。for形式には,局所的な変数を表
す識別子の集合,それらの変数の初期化及び繰返しごとの更新を指定する。終了条件が満たされる場合,
繰返しを終了し,指定された値を返す。
各識別子varの有効範囲は,本体,すべてのstep,end-test及びresult*とする。stepは省略でき,その場
合の効果は, (var init) の代わりに (var init var) と書いたものと同じとする。
for形式は,次のとおり実行される。各init形式が,左から右に順に評価される。そして,各値は,対応
する識別子varで表される変数の初期値として使われ,繰返しが開始される。
各繰返しは,end-testの評価で始まる。結果がnilであれば,本体の評価形式が順に評価される。これら
の評価形式の値は,破棄される。次に各step形式が左から右に順に評価され,それらの値が対応する変数
に代入され,次の繰返しが開始される。end-testがnil以外の値を返せば,result*が左から右に順に評価さ
れ,最後の値がfor形式の値として返される。resultが一つもなければ,for形式の値はnilとする。
例 (for ((vec (vector 0 0 0 0 0))
(i 0 (+ i 1)))
((= i 5) vec)
(setf (elt vec i) )) ⇒ #(0 1 2 3 4)
(let ((x (1 3 5 7 9)))
(for ((x x (cdr x))
(sum 0 (+ sum (car x))))
((null x) sum))) ⇒ 25
6.7 非局所的脱出
6.7.1 非局所的脱出の設定及び起動
ISLISPでは,非局所的脱出を実行する次の三つの方法を定義する。
脱出先の指定 設定する評価形式 起動する評価形式 動作
ブロック名 block return-from 静的脱出
捕そくタグ catch throw 動的脱出
タグ本体のタグ tagbody go 制御の静的移行
非局所的脱出 (non-local exit) は,それを起動した特殊形式から,脱出先 (destination) と呼ばれるプログ
ラム内のあらかじめ設定された位置へ制御を移行し,場合によってはデータの転送も行う操作とする。
静的脱出 (lexical exit) は,return-from形式から,それを静的にも動的にも含んでいるblock形式への非
局所的脱出であり,block形式がreturn-fromに指定されたオブジェクトを返すようにする。
動的脱出 (dynamic exit) は,throw形式から,それを動的に(しかし必ずしも静的ではなく)含むcatch
形式への非局所的脱出であり,catch形式がthrow形式に指定されたオブジェクトを返すようにする。
制御の静的移行 (lexical transfer of control) は,go形式から,それを静的にも動的にも含んでいるtagbody
――――― [JIS X 3012 pdf 37] ―――――
33
X 3012 : 1998 (ISO/IEC 13816 : 1997)
内のタグ付き位置への非局所的脱出とする。
非局所的脱出が起動されると,制御が移行される脱出先よりも後に設定された脱出先は,直ちに無効と
なる。
(block name form*) →<object> 特殊演算子
(return-from name result-form) 制御の移行及びデータの転送 特殊演算子
block形式は,form*を左から右に順に実行する。最後のformが正常に終了した場合,それが返す値がblock
形式の返す値とする。
block形式のnameは評価されない。それは識別子でなければならない。nameの有効範囲は,本体form*
とする。すなわち,いずれかのformにテキスト上で含まれるreturn-from形式だけが,そのブロックを脱
出できる。nameに対する束縛は,動的存在期間をもつ。
return-from形式が実行されると,result-formが評価される。評価が正常に終了すれば,その値は,
return-fromの呼出しを静的に含み,同じnameをもつ最も内側のblock形式の値として返される。
return-from形式は,blockから戻るために使う。return-from形式のnameは評価されず,識別子でなけれ
ばならない。同じnameをもつblockが,return-fromの呼出しを静的に含んでいなければならない。
result-formが生成する値は,対応するblock形式から直ちに返される。return-fromは,戻ることはなく,
また値をもたない。
blockを出た後で,そのblockから脱出しようとする場合は,エラーが発生する(エラー名control-error)。
nameが識別子でない場合は,違反とする。対応する名前をもつブロックが存在しない場合も,違反とす
る。その他のエラーについては,6.7.2参照。
例 (block x
(+ 10 (return-from x 6) 22)) ;;;悪いプログラム書法
⇒6
(defun f1 ()
(block b
(let ((f (lambda () (return-from b exit))))
··· ; 大規模計算
(f2 f)))) ⇒ f1
(defun f2 (g)
··· ; 大規模計算
(funcall g)) ⇒ f2
(f1) ⇒ exit
(block sum-block
(for ((x (1 a 2 3) (cdr x))
(sum 0 (+ sum (car x))))
((null x) sum)
(cond ((not (numberp (car x))) (return-from sum-block 0))))))
⇒0
――――― [JIS X 3012 pdf 38] ―――――
34
X 3012 : 1998 (ISO/IEC 13816 : 1997)
(defun bar (x y)
(let ((foo #car))
(let ((result
(block b1
(setq foo (lambda () (return-from b1 first-exit)))
(if x (return-from b1 second-exit) third-exit))))
(if y (funcall foo) nil)
result))) ⇒ bar
(bar t nil) ⇒ second-exit
(bar nil nil) ⇒ third-exit
(bar nil t) エラーが発生する。
(bar t t) エラーが発生する。
(catch tag-form form*) →<object> 特殊演算子
(throw tag-form result-form) 制御の移行及びデータの転送 特殊演算子
catch形式及びthrow形式は,構造化された動的な非局所的脱出機能を提供する。catch形式及びthrow形
式は,catchのtag-form及びthrowのtag-formの評価結果が,同一のオブジェクトになる場合,対応すると
呼ばれる。このオブジェクトを捕そくタグ (catch tag) と呼ぶ。捕そくタグは,数値及び文字以外のいかな
るオブジェクトでもよい。捕そくタグの比較は,eqで行う。
catch形式は,まずtag-formを評価して捕そくタグを生成し,次に各formを左から右に順に実行する。
すべてのformの実行が正常に終了した場合,最後のformの返す値が,catch形式の値として返される。
catch形式C0のform*の実行に先立って,捕そくタグT0と実行する評価形式C0との間の対応が動的に設
定され,C0の実行終了時にこの対応は解除される。同じ捕そくタグT0に対して外側の対応があれば,それ
はC0のform*の実行中は遮へいされる。すなわち,T0の最も最近(最も内側)の対応だけが見えるものと
する。
throw形式が実行されると,tag-formを評価して捕そくタグT1を生成し,次にresult-formを評価して結
果R1を生成する。T1と実行中のあるcatch形式C1との間に対応があれば,C1の値としてR1が直ちに返さ
れる。throw形式は,最上位有効範囲全体のどこにあってもよい。すなわち,C1に静的に含まれている必
要はない。
T1に対するcatch形式が存在しない場合は,エラーが発生する(エラー名control-error)。その他のエラ
ーについては,6.7.2参照。
例 (defun foo (x)
(catch block-sum (bar x))) ⇒ foo
(defun bar (x)
(for ((1 x (cdr 1))
(sum 0 (+ sum (car 1))))
((null 1) sum)
(cond ((not (numberp (car 1))) (throw block-sum 0)))))
⇒ bar
――――― [JIS X 3012 pdf 39] ―――――
35
X 3012 : 1998 (ISO/IEC 13816 : 1997)
(foo (1 2 3 4)) ⇒ 10
(foo (1 2 a 4)) ⇒0
(tagbody [{tagbody-tag | form}]*) →<object> 特殊演算子
(go tagbody-tag) 制御の移行 特殊演算子
tagbodyは,各formを左から右に順に実行し,それらの値を破棄する。最後のformの実行が正常に終了
した場合,tagbody形式は,nilを返す。
一連のtagbody-tag及びformは,まとめてtagbody形式の本体(又は,タグ本体)と呼ぶ。この本体の最
上位に現れる識別子tagbody-tagは,goによって本体内のその位置に制御を移すために使われるタグ本体
のタグ (tagbody tag) を表す。本体の最上位に現れる複合形式は,すべてformとして扱われる。リテラル
が,タグ本体の最上位にあってはならない。同一のtagbody-tagが,本体内のタグとして2回以上現れては
ならない。
タグ本体のタグに使用される名前空間は,ブロックの名前空間とは異なる。
タグ本体に静的に含まれる任意の位置で,評価形式 (go tag) は,静的原理(3.1参照)によって遮へい
される場合を除いて,タグtagに一致するtagbody-tagに制御を移すために使うことができる。
tagbodyによって設定されたタグは静的有効範囲をもつが,それが表すプログラム内の位置は,動的存在
期間をもつ。tagbodyの実行が終了した後は,goを使ってその本体内のタグ位置に制御を移行してはなら
ない。
本体のどの要素がtagbody-tagであるか,また,どれがformであるかの決定は,その要素のマクロ展開
よりも先に行われる。formがマクロ形式で,かつ,そのマクロ展開結果が記号又はリテラルである場合,
展開結果はtagbody-tagではなく,formとして扱われる。
タグ本体のタグが識別子以外である場合は,違反とする。その他のエラーについては,6.7.2参照。
備考 利用者が日常のプログラム開発でtagbody及びgoを使用することは望ましくない。これらの評
価形式の主な用法は,(マクロを使った)他の制御機能を実装する場合及び,実世界で時に必要
となる(有限状態機械のような)構造化されていない命令型の制御移動を実装する場合である。
例 (defmacro with-retry (:rest forms)
(let ((tag (gensym)))
(block ,tag
(tagbody
,tag
(return-from ,tag
(flet ((retry () (go ,tag)))
,@forms))))))
⇒ with-retry
(let ((i -5))
(with-retry
;; if-errorは,仮想的なエラー修正関数であり,
;; ISLISPでは定義していない。
――――― [JIS X 3012 pdf 40] ―――――
次のページ PDF 41
JIS X 3012:1998の引用国際規格 ISO 一覧
- ISO/IEC 13816:1997(IDT)
JIS X 3012:1998の国際規格 ICS 分類一覧
- 35 : 情報技術.事務機械 > 35.060 : 情報技術に使用される言語