ここで記述されるマクロは、Emacs Lispの基本的なwhileループを補う
ために、より洗練された高水準のループ構文要素を提供する。
CLパッケージは、loopの単純で古いスタイルの意味と、
ループマクロのループ機能として知られるきわめて強力で柔軟な
機能をどちらもサポートする。このより高度な機能は下記の節で論じられる;
see ループ機能. loopの単純なフォームはここで記述される。
loopに0個またはそれ以上のLisp式が続く場合、
(loop exprs…)は単純にその式を何度も何度も実行する
無限ループを作る。ループは暗黙のnilブロックに囲まれている。
したがって、
(loop (foo) (if (no-more) (return 72)) (bar))
は正確に下記と同等である。
(block nil (while t (foo) (if (no-more) (return 72)) (bar)))
式のどれもが単なるシンボルの場合、loopはその代わりに後に記述される ループマクロ仕様と解釈される。(これは実際は制限ではない。上記の 表記法での単なるシンボルは単純に変数の値にアクセスして 捨て去るからである。)
このマクロは一般的な繰り返しループを作る。それぞれのspecは下記の フォームである:
(var [init [step]])
ループは下記のように働く: 最初に、それぞれのvarはlet
フォームによるかのように関連づけられたinitの値に束縛される。
それから、ループのそれぞれの繰り返しではend-testが評価される;
真の場合、ループは終了する。そうでなければ、本体formsが
評価され、それぞれのvarは関連づけられたstep式に
(psetqフォームによるかのように)設定され、次の繰り返しが始まる。
一度end-testが真になると、resultフォームはdoにより
戻される結果を生成するために(varはまだその値に束縛している
状態で)評価される。
doループ全体は暗黙のnilブロックに囲まれているので、
どんなときもループを中断して出るために(return)を使える。
resultフォームがない場合、ループはnilを戻す。与えられた
varがstepフォームを持たない場合、initの値に
束縛されるが、その他の点ではdoループの間(コードが明示的に
修正しない限り)修正されない; この場合はループの周りに
(let ((var init)) …)を置くことの単なる
簡略表記法である。initも省略される場合その既定値はnil
であり、この場合は再びletとの類似にしたがって単なる
‘var’が‘(var)’の場所に使うことができる。
この例(Steeleから)は、リストfooとbarからの連続する値の
対に関数fを適用するループを説明する; それは呼び出し
(mapcar* 'f foo bar)と同等である。ループは本体forms
をまったく持たず、ループの残りの副作用としてすべての仕事をすることに
注意せよ。
(do ((x foo (cdr x))
(y bar (cdr y))
(z nil (cons (f (car x) (car y)) z)))
((or (null x) (null y))
(nreverse z)))
let*がletに対応するように、これはdoに対応する。
特に、初期値はletによってのようにではなくlet*
によってのように束縛され、stepはpsetqによってのようにではなく
setqによってのように代入される。
上記のループを格別の方法は以下の通り:
(do* ((xp foo (cdr xp))
(yp bar (cdr yp))
(x (car xp) (car xp))
(y (car yp) (car yp))
z)
((or (null xp) (null yp))
(nreverse z))
(push (f x y) z))
これはリストの要素を横切って繰り返す、より特殊化されたループである。
listはリストへ評価されなければならない; 本体formsは
varがそれぞれのリストの要素に順に束縛された状態で実行される。
最後に、resultフォーム(またはnil)がループから戻される
結果を生じるために、varがnilに束縛された状態で
評価される。ループは暗黙のnilブロックで囲まれる。
これは指定された回数繰り返す、より特殊化されたループである。本体は
varがゼロ(を含む)からcount(を含まない)までの整数に順に
束縛された状態で実行される。それからresultフォームが
ループフォームの戻り値を得るために、varが繰り返しの総回数に
束縛された状態(すなわち、(max 0 count))で評価される。
ループは暗黙のnilブロックで囲まれる。
このループはすべてのinternされたシンボル上を繰り返す。obarrayが
指定されnilでない場合、そのobarray中のすべてのシンボル上をルー
プする。それぞれのシンボルに対して、本体formsはvarがそのシ
ンボルに束縛された状態で評価される。シンボルは不定の順序で訪問される。
その後、resultフォームがあれば戻り値を得るために(varが
nilに束縛された状態で)評価される。ループは暗黙のnilブロッ
クで囲まれる。
これはobarray引数が省略されている点を除いてdo-symbolsと
同一である; 常に既定のobarrayの上で繰り返す。
ベクタやリスト上の繰り返し用のいくつかの他の関数はSee 列上のマッピング.