defuns ¶の長さを求めよwhile
ループを用いた設計は定型的なものです。関数に渡される引数はファイルのリストです。前述の通り(while
ループとリストを参照)、リストに要素が含まれている場合はループ本体を評価し、リストが空の場合はループを抜けるように while
ループを記述できます。この設計を機能させるには、ループ本体に、本体が評価されるたびにリストを短縮する式を含める必要があり、そうすることで最終的にリストが空になります。一般的な手法は、本体が評価されるたびに、リストの値をそのリストの
CDR の値に設定することです。
テンプレートは以下のようになっています。
(while test-whether-list-is-empty body... set-list-to-cdr-of-list)
また、while ループが返すのは nil(真偽判定の評価結果)であり、ループ本体内でのいかなる評価結果でもないことに注意してください。(ループ本体内の評価は、副作用のために行われます。)しかし、lengths&
リストを設定する式は本体の一部であり、関数全体として返したい値はまさにこの値です。これを実現するために、while ループを let 式で囲み、let 式の最後の要素に lengths& リストの値が含まれるようにします。(インクリメントカウンタを用いたループ例を参照してください。)
こうした考察から、直ちに関数そのものへと至る:
;;; Use while loop.
(defun lengths-list-many-files (list-of-files)
"Return list of lengths of defuns in LIST-OF-FILES."
(let (lengths-list) ;;; true-or-false-test (while list-of-files (setq lengths-list (append lengths-list ;;; Generate a lengths’ list. (lengths-list-file (expand-file-name (car list-of-files)))))
;;; Make files’ list shorter. (setq list-of-files (cdr list-of-files))) ;;; Return final value of lengths’ list. lengths-list))
expand-file-name
は、ファイル名を絶対長パス形式に変換する組み込み関数です。この関数は、呼び出し元のディレクトリ名を使用します。
したがって、Emacsが/usr/local/share/emacs/22.1.1/lisp/emacs-lisp/ディレクトリを巡回している際に、debug.elに対してexpand-file-nameが呼び出されると、
debug.el
なる
/usr/local/share/emacs/22.1.1/lisp/emacs-lisp/debug.el
この関数定義における唯一のその他の新要素は、まだ検討されていない関数 append
であり、これについては別途短い節を設ける価値がある。