--- title: 自分でmaxを定義する(汚い実装) author: kazu634 date: 2008-09-30 url: /2008/09/30/_1118/ wordtwit_post_info: - 'O:8:"stdClass":13:{s:6:"manual";b:0;s:11:"tweet_times";i:1;s:5:"delay";i:0;s:7:"enabled";i:1;s:10:"separation";s:2:"60";s:7:"version";s:3:"3.7";s:14:"tweet_template";b:0;s:6:"status";i:2;s:6:"result";a:0:{}s:13:"tweet_counter";i:2;s:13:"tweet_log_ids";a:1:{i:0;i:4315;}s:9:"hash_tags";a:0:{}s:8:"accounts";a:1:{i:0;s:7:"kazu634";}}' categories: - gauche - Lisp ---

id:SaitoAtsushiさんからせっかく教えてもらうも、applyをつかったうまい方法は思いつかず。。。とりあえずやっつけの汚い実装をする。問題は再帰で二回目以降が呼び出されるときに、引数が「*1」みたいになることが問題(それ以外の場合はあり得ない)のだから、

場合に、(car リスト)を返す手続きを作ってあげればとりあえずは解決する。つまり:

(define (select lis)
(if (and (= 1 (my_length lis)) (list? (car lis)))
(car lis)
lis))

このような手続きだ。これをふまえた上で定義するとこうなった:

(define (my_max . lis)
(cond [(null? lis) #f]
[(= (my_length (select lis)) 1) (car (select lis))]
[(= (my_length (select lis)) 2) (cond [(<= (car (select lis)) (cadr (select lis))) (cadr (select lis))]
[(>= (car (select lis)) (cadr (select lis))) (car (select lis))])]
[(>= (my_length (select lis)) 3) (cond [(<= (car (select lis)) (cadr (select lis))) (my_max (cons (cadr (select lis)) (cddr (select lis))))]
[(>= (car (select lis)) (cadr (select lis))) (my_max (cons (car (select lis)) (cddr (select lis))))])]))

なんだかこれは面倒だ。絶対にもっと簡単な書き方があるような気がする。

追記:

ふと振り返ってみたら、プログラミングGaucheでpick-greater, max-numberというのが書いてあった。fold手続きを使っている。可変長引数はリストになるからそれをそのまま渡せばいいのかな?

(define (max-number lis)
(fold
(lambda (a b)
(if (< a b)
b
a))
(car lis) (cdr lis)))
(define (my_max . args)
(max-number args))

もしかしたら、可変長引数というのは結局リストになるのだから、「リストの中で一番大きい数を探す手続き」が書ければ、「可変長引数の中で一番大きな数を探す手続き」を書いたことになるのかな?

追記の追記:

apply使ってないや。。。

*1:1 2 3 4 5