Next: , Previous: , Up: 制御構造   [Contents][Index]


4.6 繰り返し

ここで記述されるマクロは、Emacs Lispの基本的なwhileループを補う ために、より洗練された高水準のループ構文要素を提供する。

Special Form: loop forms…

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はその代わりに後に記述される ループマクロ仕様と解釈される。(これは実際は制限ではない。上記の 表記法での単なるシンボルは単純に変数の値にアクセスして 捨て去るからである。)

Special Form: do (spec…) (end-test [result…]) forms…

このマクロは一般的な繰り返しループを作る。それぞれのspecは下記の フォームである:

(var [init [step]])

ループは下記のように働く: 最初に、それぞれのvarlet フォームによるかのように関連づけられたinitの値に束縛される。 それから、ループのそれぞれの繰り返しではend-testが評価される; 真の場合、ループは終了する。そうでなければ、本体formsが 評価され、それぞれのvarは関連づけられたstep式に (psetqフォームによるかのように)設定され、次の繰り返しが始まる。 一度end-testが真になると、resultフォームはdoにより 戻される結果を生成するために(varはまだその値に束縛している 状態で)評価される。

doループ全体は暗黙のnilブロックに囲まれているので、 どんなときもループを中断して出るために(return)を使える。

resultフォームがない場合、ループはnilを戻す。与えられた varstepフォームを持たない場合、initの値に 束縛されるが、その他の点ではdoループの間(コードが明示的に 修正しない限り)修正されない; この場合はループの周りに (let ((var init)) …)を置くことの単なる 簡略表記法である。initも省略される場合その既定値はnil であり、この場合は再びletとの類似にしたがって単なる ‘var’が‘(var)’の場所に使うことができる。

この例(Steeleから)は、リストfoobarからの連続する値の 対に関数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)))
Special Form: do* (spec…) (end-test [result…]) forms…

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))
Special Form: dolist (var list [result]) forms…

これはリストの要素を横切って繰り返す、より特殊化されたループである。 listはリストへ評価されなければならない; 本体formsvarがそれぞれのリストの要素に順に束縛された状態で実行される。 最後に、resultフォーム(またはnil)がループから戻される 結果を生じるために、varnilに束縛された状態で 評価される。ループは暗黙のnilブロックで囲まれる。

Special Form: dotimes (var count [result]) forms…

これは指定された回数繰り返す、より特殊化されたループである。本体は varがゼロ(を含む)からcount(を含まない)までの整数に順に 束縛された状態で実行される。それからresultフォームが ループフォームの戻り値を得るために、varが繰り返しの総回数に 束縛された状態(すなわち、(max 0 count))で評価される。 ループは暗黙のnilブロックで囲まれる。

Special Form: do-symbols (var [obarray [result]]) forms…

このループはすべてのinternされたシンボル上を繰り返す。obarrayが 指定されnilでない場合、そのobarray中のすべてのシンボル上をルー プする。それぞれのシンボルに対して、本体formsvarがそのシ ンボルに束縛された状態で評価される。シンボルは不定の順序で訪問される。 その後、resultフォームがあれば戻り値を得るために(varnilに束縛された状態で)評価される。ループは暗黙のnilブロッ クで囲まれる。

Special Form: do-all-symbols (var [result]) forms…

これはobarray引数が省略されている点を除いてdo-symbolsと 同一である; 常に既定のobarrayの上で繰り返す。

ベクタやリスト上の繰り返し用のいくつかの他の関数はSee 列上のマッピング.


Next: , Previous: , Up: 制御構造   [Contents][Index]