練習 リストの最大値を返す
ここまで記述したLispの基本を踏まえて練習をいくつかやってみる.この頁ではリストの最大値を返す関数を作成してみる.
この頁では
(my_max リスト)により,リストの最大値を返す関数の作成を通してLispプログラミングに慣れることを目標にする.
関数my_maxを再帰で実装した例を以下に示す.
;; 引数のリストのから最大値を返す関数(再帰版) (defun my_max (x) (if (null (cdr x)) ;; 基底.リストの要素数が1の場合. (car x) ;; リストの要素数が2以上の場合. ;; 再帰呼び出しをして結果を局所変数local_maxに格納. (progn (let ((local_max (my_max (cdr x)))) ;; リストの先頭とlocal_maxを比較して大きい方を返す. (if (> (car x) local_max) (car x) local_max))))) ;; ドライバ (format t "max = ~A~%" (my_max '(5 6 4 10 7 9 1)))この例では,my_maxの引数のリストのcar部とmy_maxによって求めたcdr部の最大値を比較して最大値を求めている.また,再帰呼び出しの結果をif式の条件式と真の時の二箇所で使用するので,局所変数local_maxを使用している.letの引数はリストのリストであることに注意する.以下実行結果
$ clisp my_max1.lisp max = 10
今度は関数my_maxをループで実装してみる.
;; 引数のリストのから最大値を返す関数(ループ版) (defun my_max (x) ;; 最大値を格納する局所変数max (let ((max (car x))) ;; 引数のリストの各要素をループ変数aに格納していく (dolist (a x) (if (< max a) (setf max a) max)) ;; let式の返り値としてmaxを指定. max)) ;; ドライバ (format t "max = ~A~%" (my_max '(5 6 4 10 7 9 1)))今回はdolistを使用した.これはPerlのforeachのような関数である.どうやらdolistの返り値は(たぶん)常にnilになっている.したがって,let式の最後がdolistだとlet式の返り値(これはそのままmy_maxの返り値となる)が常にnilになってしまうので,let式の最後の式にmaxと書いてmaxの値を返すようにした(※).実行結果は再帰版と同じである.
※実はこれでハマった.