#:g1: coopsの紹介

Posted 2014-09-01 15:00:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の245日目です。

coopsとはなにか

 coopsは、Felix Winkelmann氏作のChicken用のオブジェクト指向システムです。Tiny CLOSのChicken版もありますが、Chickenとしてはこっちが推奨とのことです。

パッケージ情報

パッケージ名coops
Chicken eggs:coops - The Chicken Scheme wiki

インストール方法

$ sudo chicken-install coops

すれば、

(use coops)

(require-extension coops)

 基本的なクラスが coops-primitive-objects モジュールになっているので、こっちもuseして使うと良いかなと思います。

試してみる

 coopsの大元は、Dorai Sitaram氏のCLOS風のオブジェクト指向システムのScmObjとのことで、これを拡張したものだそうです。ScmObjを眺めてみると、こっちの方は命名規則等がCLOSっぽい様子。

 CLOS風ということで大体想像が付く所ですが、

がサポートされています。

 コードの文法的な特徴としては、メソッドの定義の括弧の位置がTiny CLOS系と違うというのがあります。
Tiny CLOS系(S式時代のDylanも)は、Common Lispのように

(define-method foo ((x <class>)) ...)

ですが、coopsは、

(define-method (foo (x <class>)) ...)

のようにSchemeの関数定義と合せてあります。
元になったScmObjもTiny CLOS系なのでcoopsでの変更の様子。

 また、メソッドコンビネーションは、

(define-method (latumapic) 
  (write-line "おはよう日本!"))

(latumapic) ;>> おはよう日本!

(define-method (latumapic before:) (write-line "== before"))

(define-method (latumapic after:) (write-line "== after"))

(define-method (latumapic around:) (write-line "==>> around") (call-next-method) (write-line "==<< around"))

(latumapic) ;>> ==>> around ;>> == before ;>> おはよう日本! ;>> == after ;>> ==<< around

のような感じで、Common Lispの人にはお馴染の動作です。

 ということで今回もBankAccountを書いてみます。

(use coops
     coops-primitive-objects
     miscmacros)

(define-class <bank-account> () ((dollars initform: 0 accessor: dollars)))

(define-generic (deposit a x))

(define-generic (withdraw a x))

(define-method (deposit (a <bank-account>) (x <integer>)) (inc! (dollars a) x))

(define-method (withdraw (a <bank-account>) (x <integer>)) (dec! (dollars a) (min x (dollars a))))

(define *my-account* (make <bank-account> 'dollars 200))

(dollars *my-account*) ;=> 200

(deposit *my-account* 50) ;=> 250

(withdraw *my-account* 100) ;=> 150

(withdraw *my-account* 200) ;=> 0

(define-class <stock-account> (<bank-account>) ((num-shares initform: 0 accessor: num-shares) (price-per-share initform: 30 accessor: price-per-share)))

(define-method ((setter dollars) (o <stock-account>) (x <integer>)) (set! (num-shares o) (/ x (price-per-share o))) (dollars o))

(define-method (dollars (o <stock-account>)) (* (num-shares o) (price-per-share o)))

(define *my-stock* (make <stock-account> 'num-shares 10))

(dollars *my-stock*) ;=> 300

(set! (dollars *my-stock*) 600) ;=> 600

(deposit *my-stock* 60) ;=> 660

(num-shares *my-stock*) ;=> 22

(withdraw *my-stock* 120) ;=> 540

(num-shares *my-stock*) ;=> 18

という感じで、ほぼCLOSと同じ感覚で書けます。

まとめ

 今回は、coopsを紹介してみました。
このオブジェクト指向システムにどこまで拡張性があるのかは調べていませんが、通常使う分にはこれで問題なさそうですね。

comments powered by Disqus