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


4.7.6 その他の節

この節は残りのループ節を記述する。

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は蓄積であるべきである; doreturnifunless節。いくつかの節は、それらをandで 切り離して結合されてもよい。

これらの節には、elseと、条件が偽の場合に実行される1つまたは 複数の節が続いてもよい。すべての構文要素には、付加的に語end (それは入れ子のifの中でelseand をあいまいでなくするために使われてもよい)が続いてもよい。

実際の条件式の非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...

このキーワードはループ自身が始まる前(しかしforwithに 要求されるすべての変数がその初期値に束縛された後)に実行される1つかそれ 以上のLispフォームを導入する。initially節はどこにでも 現れることができる; いくつかある場合、それらはループに現れる順に 実行される。キーワードdoは付加的である。

finally [do] forms...

これはループが終わった後(たとえば、forwhileの要求で)に 実行されるLispフォームを導入する。initiallyfinally節は ループ構文要素のどこに現れてもよいが、それらはループのそれぞれ始まりや 終わりに(指定された順序で)実行される。

finally return form

これは、戻り値を得るためにループ終了後に実行されるべきform について述べる(これやcollectreturnのようないくつか他の 節がないと、ループは単にnilを戻すだろう)。forwithintoによって束縛された変数は、formが 実行されるときにその最後の値をまだ含んでいる。

do forms...

doには、ループ本体で暗黙のprognとして実行される任意の 数のLisp式が続いてもよい。この節の例の多くはdoの使用法を 説明する。

return form

この節は、ループが直ちに戻るようにする。それに続くLispフォームは 評価され、loopフォームの戻り値を与える。finally節は、 もしあったとしても実行されない。もちろん、returnは一般に ifunlessの内部で使われるが、それはトップレベルのループ 節での使用は、そのループは決して1度以上“ループ”に到達しないことを 意味するからである。

節‘return form’は‘do (return form)’(あるいは ループが名付けられている場合はreturn-from)と同等である。 しかし、return節は若干効率的に実装されている。

loopへユーザ拡張を加える(たとえばsetfに対する defsetfに比較できるような)高水準の方法はないが、この パッケージは、与えられたシンボルがトップレベルループ節やfor節に 出会ったときにそれぞれ呼び出される関数であるcl-loop-handlercl-loop-for-handlerと呼ばれる2つの属性を提供する。詳細は ファイルcl-macs.elのソースコードを調べよ。

このパッケージのloopマクロはCommon Lispのそれと互換だが、 loop-finishやデータ型指定子のようないくつかの機能は 実装されていない。当然、キーマップやオーバレイ、インターバル、 フレーム、ウィンドウ、バッファ上で繰り返すfor節はEmacs特有の 拡張である。