#:g1: CommonORBITの紹介

Posted 2014-05-13 15:00:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の134日目です。

CommonORBITとはなにか

 CommonORBITは、Koenraad de Smedtによるプロトタイプベースのオブジェクト指向システムです。1987年頃開発されていました。
元は、Luc Steels氏が開発していたFranz Lisp上でのオブジェクト指向システムであるOrbitをCommon Lispに実現したものとのこと。

パッケージ情報

パッケージ名CommonORBIT
Quicklisp×
参考文献Object-oriented and frame-based programming in CommonORBIT(PDF)
CMU AIレポジトリPackage: lang/lisp/oop/non_clos/corbit/

インストール方法

 上記のCMUのサイトからダウンロードしてロードします。もしくは、ASDFに対応したものがありますので、興味のある方は試してみて下さい

Quicklispのlocal-projects以下に展開すれば、

(ql:quickload :commonorbit)

でもロード可能です。

試してみる

 これまでのオブジェクト指向システムの紹介と同様に、BankAccountというのを書いてみます。

(defobject bank-account
  (dollars :value 0))

(show 'bank-account) ;>> An object with name BANK-ACCOUNT. ;>> with DOLLARS :VALUE = 0 ;=> BANK-ACCOUNT

(defaspect deposit 'bank-account :function (self n) (setaspect 'dollars self (+ n (dollars self)) :value) (dollars self))

(defaspect withdraw 'bank-account :function (self n) (setaspect 'dollars self (max 0 (- (dollars self) n)) :value) (dollars self))

(defparameter *my-account* (a bank-account (dollars 200))) ;=> *MY-ACCOUNT*

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

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

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

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

 CommonORBITでは、メソッドはASPECTと呼ばれるようです。
所謂スロットとそのアクセサもASPECT。DEFOBJECTでスロットを定義するとASPECTも定義されます。
単体のASPECTはDEFASPECTで定義します。
Aや、ANでプロトタイプを複製します。

 また、ユーティリティで、>>というのが定義されていて、

(>> a b c)
;==> (c (b a))

という展開をするようになっているので、これを使えばメッセージセンド風味にも書けます。

 次に、bank-accountを継承したstock-account

(defobject stock-account
  bank-account
  (num-shares :value 0)
  (price-per-share :value 30))

(show 'stock-account) ;>> An object with name STOCK-ACCOUNT. ;>> It is a client of BANK-ACCOUNT. ;>> with PRICE-PER-SHARE :VALUE = 30 ;>> with NUM-SHARES :VALUE = 0 ;=> STOCK-ACCOUNT

(defaspect set-dollars 'stock-account :function (self n) (setaspect 'num-shares self (/ n (price-per-share self)) :value) (setaspect 'dollars self n :value) (dollars self))

(defaspect dollars 'stock-account :function (self) (* (num-shares self) (price-per-share self)))

(defaspect deposit 'stock-account :function (self n) (set-dollars self (+ n (dollars self))))

(defaspect withdraw 'stock-account :function (self n) (set-dollars self (+ (- n) (dollars self))))

 継承元は、DEFOBJECTの定義のASPECTの前に列挙します。

(defparameter *my-stock* (a stock-account (num-shares 10)))
;=>  *MY-STOCK*

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

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

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

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

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

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

さらにCommonORBITは多重継承をサポートしています。

(defobject a 
  (@a :value 0))

(defobject b (@b :value 1))

(defobject c (@c :value 2))

(defobject abc a b c (@d 3))

(show 'abc) ;>> An object with name ABC. ;>> It is a client of A, B and C. ;>> with @D :VALUE = 3 ;=> ABC

(defaspect foo 'a :function (self) (write-line "おはよう日本"))

(defaspect bar 'b :function (self) (write-line "こんにちは日本"))

(defaspect baz 'c :function (self) (write-line "こんばんは日本"))

(foo 'abc) ;>> おはよう日本 ;>> ;=> "おはよう日本"

(bar 'abc) ;>> こんにちは日本 ;>> ;=> "こんにちは日本"

(baz 'abc) ;>> こんばんは日本 ;>> ;=> "こんばんは日本"

(foo (an abc)) ;>> おはよう日本 ;>> ;=> "おはよう日本"

まとめ

 今回は、CommonORBITを紹介してみました。CommonORBITの元になったOrbitが、1981年位のものということはLispでプロトタイプベースのオブジェクト指向システムというのもかなり古くからあるんですね。

comments powered by Disqus