この節は残りのループ節を記述する。
with var = value
この節はループの周りである値をある変数に束縛するが、その他の点では ループ中にその変数を孤立させる。下記のループは基本的に同等である:
(loop with x = 17 do ...) (let ((x 17)) (loop do ...)) (loop for x = 17 then x do ...)
当然、変数varはループの残りでなんらかの用途に 使われるかもしれない。たとえば:
(loop for x in my-list with res = nil do (push x res) finally return res)
このループは、res
に蓄積されている新しいリストの先頭に
my-list
の要素を挿入し、それからループの終わりにリストres
を戻す。その効果はcollect
節の効果と類似しているが、要素は
末尾にではなくres
の先頭に置かれていくという事実のために
逆順になる。
=
項を省略した場合、その変数はnil
に初期化される
(したがって上記の例の‘= nil’は不要である)。
with
によって作られる束縛は、let*
によってのように、
既定では順次である。ちょうどfor
節のように、with
節はその
代わりに束縛がlet
によって作られるようにするためにand
と
結合されえる。
if condition clause
この節は、指定された条件が真の場合だけ、それに続くループを実行する。
下記のclauseは蓄積であるべきである; do
やreturn
、
if
、unless
節。いくつかの節は、それらをand
で
切り離して結合されてもよい。
これらの節には、else
と、条件が偽の場合に実行される1つまたは
複数の節が続いてもよい。すべての構文要素には、付加的に語end
(それは入れ子のif
の中でelse
やand
をあいまいでなくするために使われてもよい)が続いてもよい。
実際の条件式の非nil
の値は、“then”部の中で名前it
として
利用できる。たとえば:
(setq funny-numbers '(6 13 -1))
⇒ (6 13 -1)
(loop for x below 10
if (oddp x)
collect x into odds
and if (memq x funny-numbers) return (cdr it) end
else
collect x into evens
finally return (vector odds evens))
⇒ [(1 3 5 7 9) (0 2 4 6 8)]
(setq funny-numbers '(6 7 13 -1))
⇒ (6 7 13 -1)
(loop <same thing again>)
⇒ (13 -1)
2つの節を“then”部に置くためのand
の使用に注意せよ。その
1つはそれ自身if
節である。end
は、通常は付加的であるが、
else
が最も外側のif
節を参照することを
明らかにするためにここでは必要だったことにも注意せよ。第1の場合、
ループはxの奇数と偶数のリストのベクタを戻す。第2の場合、奇数7は
funny-numbers
の一つなのでループは早く戻る; 実際の戻り値は、
memq
呼び出しの結果に基づく。
when condition clause
この節は単にif
の同義語である。
unless condition clause
unless
節は、条件の意味が逆であることを除いてちょうどif
に
似ている。
named name
この節は、ループを囲む暗黙のブロックにnil
以外の名前を与える。
nameはブロック名として使われるシンボルである。
initially [do] forms...
このキーワードはループ自身が始まる前(しかしfor
やwith
に
要求されるすべての変数がその初期値に束縛された後)に実行される1つかそれ
以上のLispフォームを導入する。initially
節はどこにでも
現れることができる; いくつかある場合、それらはループに現れる順に
実行される。キーワードdo
は付加的である。
finally [do] forms...
これはループが終わった後(たとえば、for
やwhile
の要求で)に
実行されるLispフォームを導入する。initially
やfinally
節は
ループ構文要素のどこに現れてもよいが、それらはループのそれぞれ始まりや
終わりに(指定された順序で)実行される。
finally return form
これは、戻り値を得るためにループ終了後に実行されるべきform
について述べる(これやcollect
やreturn
のようないくつか他の
節がないと、ループは単にnil
を戻すだろう)。for
や
with
、into
によって束縛された変数は、formが
実行されるときにその最後の値をまだ含んでいる。
do forms...
語do
には、ループ本体で暗黙のprogn
として実行される任意の
数のLisp式が続いてもよい。この節の例の多くはdo
の使用法を
説明する。
return form
この節は、ループが直ちに戻るようにする。それに続くLispフォームは
評価され、loop
フォームの戻り値を与える。finally
節は、
もしあったとしても実行されない。もちろん、return
は一般に
if
やunless
の内部で使われるが、それはトップレベルのループ
節での使用は、そのループは決して1度以上“ループ”に到達しないことを
意味するからである。
節‘return form’は‘do (return form)’(あるいは
ループが名付けられている場合はreturn-from
)と同等である。
しかし、return
節は若干効率的に実装されている。
loop
へユーザ拡張を加える(たとえばsetf
に対する
defsetf
に比較できるような)高水準の方法はないが、この
パッケージは、与えられたシンボルがトップレベルループ節やfor
節に
出会ったときにそれぞれ呼び出される関数であるcl-loop-handler
や
cl-loop-for-handler
と呼ばれる2つの属性を提供する。詳細は
ファイルcl-macs.elのソースコードを調べよ。
このパッケージのloop
マクロはCommon Lispのそれと互換だが、
loop-finish
やデータ型指定子のようないくつかの機能は
実装されていない。当然、キーマップやオーバレイ、インターバル、
フレーム、ウィンドウ、バッファ上で繰り返すfor
節はEmacs特有の
拡張である。