sheepleでディスパッチ
sheepleはCLOSの総称関数の様なディスパッチ機構を持っています。
まず、「メッセージ」を定義し、「メッセージ」への各オブジェクトの「応答(reply)」を定義していきます。
「メッセージ」がCLOSの総称関数、「応答」がCLOSのメソッドにあたります。
(defmessage test (obj)) (defvar *obj1* (object)) (defreply test ((obj *obj1*)) (write "*obj1*")) (test *obj1*) ;; -> "*obj1*" ;; => nil
CLOSと明に違うのは、sheepleにはクラスがないため、「応答」の特定がオブジェクトに対して行なわれるところでしょうか?
ただし、「応答」の特定がオブジェクのみだと不便であるため、parentsで指定したオブジェクトに特定された「応答」も選択されます。
(defvar *obj2* (object :parents (list *obj1*))) (test *obj2*) ;; -> "*obj1*" ;; => nil
CLのオブジェクトのプロトタイプも用意されていて、「応答」の特定の際に指定できます。
(defmessage add (a b)) (defreply add ((a =number=) (b =number=)) (+ a b)) (add 10 20) ;; => 30 (defreply add ((a =string=) (b =string=)) (concatenate 'string a b)) (add "hoge" "huga") ;; => "hogehuga"
最後に、fibをsheepleで書いてみます。
(defmessage fib (n)) (defreply fib ((n 0)) 1) (defreply fib ((n 1)) 1) (defreply fib (n) (+ (fib (- n 1)) (fib (- n 2))))
既に分かっている応答については、defmessageで定義できるみたいです。
(defmessage fib (n) (:reply ((n 0)) 1) (:reply ((n 1)) 1) (:reply (n) (+ (fib (- n 1)) (fib (- n 2)))))