while ループと List ¶while
ループを制御する一般的な方法は、リストに要素があるかどうかを判定することです。要素があればループが繰り返され、なければ繰り返しが終了します。これは重要な手法であるため、具体例を作成して解説します。
リストに要素が含まれているかを確認する簡単な方法は、そのリストを評価することです。要素がない場合は空リストとなり、空リスト () が返されます。これは nil または false
の同義語です。一方、要素を持つリストは、評価時にそれらの要素を返します。Emacs Lisp では nil 以外のあらゆる値を真とみなすため、要素を返すリストは while ループにおいて真と判定されます。
例えば、以下の setq 式を評価することで、変数 empty-list に nil を設定できます。
(setq empty-list ())
setq 式を評価した後、シンボルの後にカーソルを置いて C-x
C-e と入力すれば、通常通りに変数 empty-list
を評価できます。すると、エコーエリアに nil が表示されます:
empty-list
一方、変数を要素を持つリストとして設定すると、次の2つの式を評価してわかるように、変数を評価した際にそのリストが表示されます。
(setq animals '(gazelle giraffe lion tiger)) animals
このように、リスト animals に項目があるかどうかを判定する while ループを作成するには、ループの前半部分を次のように記述します。
(while animals
...
while が第1引数をテストする際、変数 animals が評価されます。これはリストを返します。そのリストに要素がある限り、while はテスト結果を真とみなしますが、リストが空の場合は、テスト結果を偽とみなします。
while
ループが無限に回り続けるのを防ぐため、最終的にリストを空にするための何らかの仕組みを設ける必要があります。よく用いられる手法は、while 式の後続の形式のいずれかで、リストの値をそのリストの CDR に設定することです。cdr
関数が評価されるたびにリストは短くなり、最終的に空のリストだけが残ります。この時点で、while
ループの判定は false となり、while への引数はそれ以上評価されなくなります。
例えば、変数 animals にバインドされた動物のリストは、以下の式を用いて元のリストの
CDR に設定できます。
(setq animals (cdr animals))
先ほどの式を評価し、次にこの式を評価すると、エコー領域に (giraffe lion tiger)
が表示されます。さらにこの式を評価すると、エコー領域に (lion tiger)
が表示されます。もう一度、さらにもう一度評価すると、(tiger) が表示され、続いて nil で示される空のリストが表示されます。
cdr関数を繰り返し使用することで、真偽判定が最終的にfalseとなるようにしたwhileループのテンプレートは、次のようになります。
(while test-whether-list-is-empty body... set-list-to-cdr-of-list)
このcdrのテストと利用は、リストを走査して各要素をそれぞれ1行に出力する関数にまとめることができます。