Next: , Previous: , Up: ループ機能   [Contents][Index]


4.7.3 For節

ほとんどのループは1個かそれ以上のfor節に支配される。for 節は束縛される変数を記述すると当時に、これらの変数がループ 中にどのようにステップされるか、また通常はこれらの変数に基づいた 終了条件を記述する。

asは語forの同義語である。この語の後には変数名が続き、 望む繰り返しの種類を記述するfromacrossのような語が 続く。Common Lispでは、句being theがときどき繰り返しの型の前に 来る; このパッケージではbeingtheはともに付加的である。 語eachtheの同義語であり、それに続く語は単数でも 複数でもよい: ‘for x being the elements of y’や ‘for x being each element of y’のように。どちらのフォームを 使うかは純粋にスタイルの問題である。

変数はletによるかにようにループの周りで束縛される:

(setq i 'happy)
(loop for i from 1 to 10 do (do-something-with i))
i
     ⇒ happy
for var from expr1 to expr2 by expr3

このfor節の型は数え上げのループを作る。3個の副項のそれぞれは 付加的だが、節が数え上げの節だとマークされるように少なくても1個の 項がなければならない。

3個の式はそれぞれ変数の開始値、終了値、ステップ値である。ループは、 expr1からexpr2(を含む)までを既定では上方に(expr3は 正数でなければならない)数える。from項を省略した場合、ループは 0から数える; to項を省略した場合、ループは止まらずに永久に数える (もちろん、他のループ節によって止まらない限り); by項を省略した 場合、ループは1のステップで数える。

ループの方向を示すために、語fromupfromまたは downfromに置き換えることができる。同様に、touptoまたはdowntoに置き換えることができる。たとえば、 ‘for x from 5 downto 1’はxが順に5から1までの整数を 持ちながら5回実行する。また、tobelowまたはabove に置き換えることもできる。これは制限を含むのではないことを除いて uptodowntoにそれぞれ似ている:

(loop for x to 10 collect x)
     ⇒ (0 1 2 3 4 5 6 7 8 9 10)
(loop for x below 10 collect x)
     ⇒ (0 1 2 3 4 5 6 7 8 9)

数え下げのループのためであっても、byは常に正数である。 なんらかの種類のfrom値が数え下げのループのためには必須である; ‘for x downto 5’はそれ自身まったく正しいループ節ではない。

for var in list by function

この節は、順にlistのすべての要素でvarを繰り返す。by 項を指定した場合、functioncdrの代わりにリストを 横切るために使われる; それは1個の引数をとる関数でなければならない。 たとえば:

(loop for x in '(1 2 3 4 5 6) collect (* x x))
     ⇒ (1 4 9 16 25 36)
(loop for x in '(1 2 3 4 5 6) by 'cddr collect (* x x))
     ⇒ (1 9 25)
for var on list by function

この節はlistのすべてのコンスセルでvarを繰り返す。

(loop for x on '(1 2 3 4) collect x)
     ⇒ ((1 2 3 4) (2 3 4) (3 4) (4))

byがある場合、on式がリストでなければならないという 理由はない。たとえば:

(loop for x on first-animal by 'next-animal collect x)

ここでは(next-animal x)は“動物”xをとり、動物の列 (と仮定されたもの)の中の次のものを戻すか、xが列の最後の動物の 場合はnilを戻す。

for var in-ref list by function

これは普通のin節と似ているが、varは単に一時変数ではなく、 リストの要素上のsetf可能な“参照”になる。たとえば:

(loop for x in-ref my-list do (incf x))

は正しくmy-listのそれぞれの要素の値を1つ増やす。この節は標準 Common Lispへの拡張である。

for var across array

この節はarrayのすべての要素でvarを繰り返す。arrayは ベクタまたは文字列でなければならない。

(loop for x across "aeiou"
      do (use-vowel (char-to-string x)))
for var across-ref array

この節は、varを要素上のsetf可能な参照として配列上を 繰り返す; 上記のin-refを参照のこと。

for var being the elements of sequence

この節はsequenceの要素上で繰り返す。sequenceはリストか ベクタ、文字列でなければならない。型は実行時に 決定されなければならないので、これはinまたはacross よりもいくぶん効率が悪い。節には、var2が要素の連続する インデックスに束縛されるようにするために、追加の項 ‘using (index var2)’が続いてもよい。

この節の型はloopマクロの古い版からとられており、最新のCommon Lispにはない。より古いマクロの‘using (sequence ...)’項は サポートされていない。

for var being the elements of-ref sequence

この節は、varを要素上のsetf可能な参照として列上を繰り返す; 上記のin-refを参照のこと。

for var being the symbols [of obarray]

この節は、すべてのinternされたシンボルまたはobarray中のすべての シンボル上を繰り返す。ループは、varを順にそれぞれのシンボルに 束縛して実行される。シンボルは不定の順序で訪問される。

一例として、

(loop for sym being the symbols
      when (fboundp sym)
      when (string-match "^map" (symbol-name sym))
      collect sym)

は、‘map’で始まる名前を持つすべての関数のリストを戻す。

Common Lispの語external-symbolspresent-symbolsも 認められるが、Emacs Lispではsymbolsと同等である。

重要でない実装の制限のために、一つのloopの中にシンボル、 ハッシュ表、キーマップ、オーバレイ、インターバル上で繰り返す、 1つ以上のfor節を持つと正しく動作しない。幸いにも、 そうすることが有用なことはきわめてまれだろう。for ... towhileのような他の節とこれらの節の型の一つを混ぜることは正しい ことである

for var being the hash-keys of hash-table

この節はhash-tableのエントリ上で繰り返す。それぞれのハッシュ表 エントリに対して、varはそのエントリのキーに束縛される。 ‘the hash-values’をその代わりに書いた場合、varはエントリの 値に束縛される。varvar2がハッシュ表エントリの 2つのそれぞれの部分に束縛されるように、その節に追加の項 ‘using (hash-values var2)’(hash-valuesthe に続く語の反対の語である)が続いてもよい。

for var being the key-codes of keymap

この節はkeymapのエントリ上で繰り返す。GNU Emacs 18と19では、 キーマップは連想リストまたはベクタであり、キーコードは整数または シンボルである。Lucid Emacs 19ではキーマップは特殊な新しいデータ 型であり、キーコードはシンボルまたはシンボルのリストである。繰り返しは 入れ子になったキーマップや受け継いだ親のキーマップには入らない。 キーコードではなくキーに束縛されたコマンドにアクセスするために ‘the key-bindings’を使うことができる。コードと束縛の両方に アクセスするためにusing節を加えることができる。

for var being the key-seqs of keymap

この節はkeymapとその入れ子になったキーマップで定義されるすべての キー列上で繰り返す。varはEmacs 18では文字列の値を、Emacs 19では ベクタの値をとる。文字列やベクタはそれぞれの繰り返しで 再利用されるので、それらをいつまでも保ちたいならば コピーしなければならない。同様にコマンド束縛を得るために ‘using (key-bindings ...)’節を加えることができる。

for var being the overlays [of buffer] …

この節はEmacs 19の“オーバレイ”またはLucid Emacsのバッファの “エクステント”上で繰り返す(節extentsoverlaysの 同義語である)。Emacs 18の元では、この節は1度も繰り返さない。of 項が省略された場合、現バッファが使われる。この節は、付加的な ‘from pos’や‘to pos’項も受け入れるが、指定した リージョンを重ねるオーバレイへの節に制限する。

for var being the intervals [of buffer] …

この節は不変のテキスト属性を持つバッファのすべてのインターバル上で 繰り返す。変数varは開始位置と終了位置のコンスに束縛され、 そこではある開始位置は常に前の終了位置と等しい。この節はoffromtoproperty項を許す。そこでは後の項は 指定された属性のみに検索を制限する。of項はバッファか文字列を 指定できる。この節はGNU Emacs 19のみで有用である; 他の版では、すべての バッファや文字列は1つのインターバルから成る。

for var being the frames

この節はすべてのフレーム上、すなわちEmacsファイル上で開いている Xウィンドウシステムのウィンドウで繰り返す。この節はEmacs 19の元でのみ 動作する。節screensframesの同義語である。フレームは、 selected-frameから始まるnext-frameの順序で訪問される。

for var being the windows [of frame]

この節は現フレームか指定されたframeの(Emacsの意味での)ウィンドウ 上で繰り返す(Emacs 18では常に1つのフレームだけがあり、of 項はそこでは許されない)。

for var being the buffers

この節はEmacsのすべてのバッファ上で繰り返す。それは ‘for var in (buffer-list)’と同等である。

for var = expr1 then expr2

この節は一般の繰り返しを行なう。ループを最初に通るとき、varexpr1に束縛される。2回目やそれに続く繰り返しでは、それは expr2(varの古い値を参照してもよい)を評価した値に設定される。 たとえば、これらの2つのループは実際に同じである:

(loop for x on my-list by 'cddr do ...)
(loop for x = my-list then (cddr x) while x do ...)

このforの型はどんな種類の終端条件も含まないことに注意せよ; 上記の例は、いつループが終わるかを言うためにそれとwhile節を 結合する。

then項を省略した場合、expr1は初期設定とそれに続く設定の 両方に使われる:

(loop for x = (random) when (> x 0) return x)

このループは、正数を得るまで(random)関数から乱数を取得し続けて、 その後戻る。

1つの列にいくつかのfor節を含む場合、それらは(let*setqのように)順次に扱われる。節を結合するために代わりに 語andを使うことができ、その場合は(letpsetq のように)並列に処理される。

(loop for x below 5 for y = nil then x collect (list x y))
     ⇒ ((0 nil) (1 1) (2 2) (3 3) (4 4))
(loop for x below 5 and y = nil then x collect (list x y))
     ⇒ ((0 nil) (1 0) (2 1) (3 2) (4 3))

第1のループでは、yは前の節で設定されたばかりのxの値に 基づいて設定される; 第2のループでは、xyは同時に 設定されるので、yはループを通して前回から残されたxの値に 基づいて設定される。

loopマクロの他の機能として分配があり、それは defmacroによって提供される分配と概念として類似している。 すべてのfor節のvar部分は、単なる変数の代わりに変数の リストとして与えることができる。ループ実行中に生成される値は リストでなければならない; リスト中の値は対応する変数に格納される。

(loop for (x y) in '((2 3) (4 5) (6 7)) collect (+ x y))
     ⇒ (5 9 13)

ループ分配では、変数よりも多くの値がある場合は残りの値は無視され、 値よりも多くの変数がある場合は残りの変数は値nilを取得する。 nilが変数名として使われた場合、対応する値は無視される。分配は 入れ子になってもよいし、(x . y)のような変数のドットリストも 許される。


Next: , Previous: , Up: ループ機能   [Contents][Index]