ファイヤープロジェクト
練習 リストの最大値を返す
2003-09-15T04:00+09:00   matsu
ここまで記述した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の値を返すようにした(※).実行結果は再帰版と同じである.
※実はこれでハマった.
matsu(C)
Since 2002
Mail to matsu