Common Lisp勉強中・・・ (8)

本で言う第9章, 繰り返し.
本は, 「やさしいLisp入門」.



Lispでは, 歴史的に繰り返し専用の制御機構ではなく, 再帰的な関数呼び出しの方が使われることが多い.
関数呼び出しの際には, 変数などの情報を保存するためにスタックを使用する.
これには上限があるため, doやdo*といった反復処理が利用される場合がある.


末尾呼び出し

  • 特定の条件を満たしていると, 自動的にスタックが消費されないように展開される仕組み.
  • 再帰的な関数呼び出しでも同じ.
  1. 関数値として返されるLisp式の値が関数呼び出しである場合, その関数呼び出しは末尾呼び出しになるといえる.

よく分からん.
要は, 関数の最後にある式が「関数呼び出し」だったら最適化されるってことかい?
おっ, ググッたら分かり易い解説があった.


以下の2つの条件を満たすときを末尾呼び出しと呼びます。

* ある関数が別の関数を呼び出している
* 別の関数の戻り値がそのままその関数の戻り値になる

末尾呼び出しで自分自身を呼び出しているときを末尾再帰と言います。

別の関数を呼び出していて, その呼び出した関数の返戻値をそのまま使用するならば, 末尾呼び出しってことね.
関数呼び出しの結果を足し算とか引き算とかして, 処理したらアウト, と.



一般的な繰り返し.

;; 構文
(do ((変数1 初期値1 更新値1)
     ...
     (変数N 初期値N 更新値N))
    (終了条件 doの値) 
  反復したい式
  ...
  )

doの一般的な動作.

  1. 変数1から変数Nまでを局所変数として利用可能にし, それぞれの初期値で初期化する.
  2. 終了条件が真かどうか調べる. 真ならば 5 へすすむ.
  3. 「反復したい式」部に書かれているLisp式を順番に実行する.
  4. 変数1から変数Nまでの値をそれぞれの更新値の値に変更し, 2に戻る.
  5. 処理を終了して, 「doの値」を答に返す.

初期値, 更新値は, Lisp式として実行される.
更新値の指定には, 同時に宣言している他の局所変数の値を使うことができる.
初期値や更新値は, 別に指定しなくても問題無い


do*は, doとほぼ同じで, 違いは, letとlet*のそれと同じってことで良いのかな.
局所変数の初期化とかに, 今さっき指定したばっかりの局所変数が使えるっていう.