#:g1: ObjectLISPの紹介

Posted 2014-08-26 10:30:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の238日目です。

ObjectLISPとはなにか

 ObjectLISPは、Gary L. Drescher氏作の1984、5年頃に開発された今でいうプロトタイプベースのオブジェクト指向システムです。

パッケージ情報

パッケージ名ObjectLISP
Quicklisp×

インストール方法

にソースが転がっているので適当に移植します。
compiler-letと、Lispオブジェクトのアドレスを取得する関数が処理系にあれば、恐らく簡単に移植できると思います。
SBCLなら

(defun %pointer (obj)
  (sb-kernel:get-lisp-obj-address obj))

のようなところ。

試してみる

 ObjectLISPのマニュアルもネットに転がっていますが、知っている所は残念ながら現在リンク切れ。
代りに1985年頃にCommon Lispのオブジェクト指向システムを議論するメーリングリストにマニュアルのTeX原稿が流れていたので紹介してみます〈今のlatex等でも処理できます〉。

 ObjectLISPで良く知られている話としては、Common Lispに搭載されるオブジェクト指向システムが議論された時に、(New)Flavors、CommonLoops、CommonObjectsとObjectLISPで争った的な話がありますが、自分が眺める限りでは、ObjectLISP/LMIの人達にそんなにプッシュする気はなかったような気がしています。
ちなみに、やる気満々のXerox方面では、CommonLoopsのMOPを活用してObjectLISPを実装したとのこと。
また、ObjectLISPは、1986年位のMac用の処理系であるCorel CL=Macintosh Allegro CLでは、オブジェクト指向システムとして採用されていて、GUI関係での記述で専ら使われていた様子

 ということで毎度お馴染BankAccountを書いてみます。

プロトタイプベースなのでdefkindのようなものを使わなくてもmake-objしたものをoneof/kindofでコピーして作っていけますが、一応用意されているので下記の例では使ってみました。
特徴的な構文としては、askがありますが、これは、オブジェクトのボディ内で式が評価できる感じのものです。askのボディ内とdefobfunのボディ内ではインスタンス変数が取得できるのですが、元ネタがメソッド(dollars/set-dollars)をオーバーライドさせるのが肝みたいなので下記のコードではメソッドにしています。

(defpackage :objectlisp.demo
  (:use :cl :obj)
  (:shadowing-import-from :obj
                          . #.(intersection (*:list-external-symbols :obj)
                                            (*:list-external-symbols :cl)
                                            :test #'string=)))

(cl:in-package :objectlisp.demo)

(defkind =bank-account=)

(defobfun (exist =bank-account=) (&key* (dollars 0)) (have 'dollars dollars))

(defobfun (dollars =bank-account=) () dollars)

(defobfun (set-dollars =bank-account=) (x) (setq dollars x))

(defobfun (deposit =bank-account=) (x) (set-dollars (+ (dollars) x)))

(defobfun (withdraw =bank-account=) (x) (set-dollars (max 0 (- (dollars) x))))

(defparameter *my-account* (oneof =bank-account= 'dollars 200))

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

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

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

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

(defkind =stock-account= =bank-account=)

(defobfun (exist =stock-account=) (&key* (num-shares 0) (price-per-share 30)) (have 'num-shares num-shares) (have 'price-per-share price-per-share))

(defobfun (set-dollars =stock-account=) (x) (setq num-shares (/ x price-per-share)) (dollars))

(defobfun (dollars =stock-account=) () (* num-shares price-per-share))

(defparameter *my-stock* (oneof =stock-account= 'num-shares 10))

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

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

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

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

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

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

まとめ

 今回は、ObjectLISPを紹介してみました。
最初のプロトタイプベースの言語と言われるSelfが1980年代中期に誕生ということなので、ObjectLISPも最初期のものの一つなのではないでしょうか。

comments powered by Disqus