Displaying posts written in

7月 2009

Common LispでFizz-Buzz問題・総称関数を使って

総称関数の練習のために、Fizz-Buzz問題を総称関数を使って解いてみた。独自のメソッド結合まで使った、無駄に大掛かりな物になっている。

(defun strcat (&rest strings)
  (apply 'concatenate `(string ,@strings)))
 
(define-method-combination strcat :identity-with-one-argument t)
 
(defgeneric fizz-buzz-method (mod3 mod5)
  (:documentation "mod3が0ならFizz, mod5が0ならBuzz")
  (:method-combination strcat))
 
(defmethod fizz-buzz-method strcat ((mod3 (eql 0)) mod5)
  "Fizz")
 
(defmethod fizz-buzz-method strcat (mod3 (mod5 (eql 0)))
  "Buzz")
 
(defmethod fizz-buzz-method strcat (mod3 mod5)
  "")
 
(defun empty-p (seq)
  (if (= 0 (length seq)) nil seq))
 
(defun fizz-buzz (n)
  (format t "~a~%" (or (empty-p (fizz-buzz-method (mod n 3) (mod n 5))) n)))

総称関数の使い勝手はHaskellやErlangのパターンマッチと似たところがあるが、マッチするメソッドが一度に全部手に入り、それらを結合できるところが決定的に違う。