2492. Re. 2491 Re. 2490 Re. 2489 Gauche...
亀田馬志 (Nov 23, 2009)
>>LOLOLさん
>私の理解では、このR5RSにあるオブジェクトの意味が逆にピントこなかったんですよ。
う??ん。確かに。
オブジェクトって「手垢が付いていて」「使いまわされてる」言葉ですし、実際、「何を指してオブジェクトと
言うのか」定義がハッキリしてない、と言えばしてないですね。これこそ「工学的な曖昧な」言葉と言うか。
>OOPでは、基本的にすべてがtopクラスのサブクラスという構造をとります。
ええとですね。ANSI Common LispのCLOSも全てTクラス、と呼ばれるクラスのサブクラス、と言う構造を取って
いるんです。これちょっとあとで見てみますか。
>いわゆるprimitive型というのがあるのは純粋OOPではなくて、pureOOPだと数値も文字もtopclassのサブクラ
スに位置づけられます。
>その点、Javaなんかはprimitive型があるから、純粋なOOPじゃないですね。
逆にMatz氏はRubyは純粋なOOPとして設計したんじゃなかったのかしら?
全然OOP使わないんで分からないんですけど(笑)。
>これは、次のGauche入門立ち読み版を今日、なんとなく読んでいて知ったんです。
これもそうなんですよね。Schemeで言う「オブジェクト」なのか単なるOOPの説明してるのか……。
おそらくCLOS的な機能組み込む為にこう言う設計したんだと思いますけど……。OOP的なオブジェクトとScheme
で言うオブジェクトがごっちゃで書かれてる気が(笑)。
>最初に少し安心させることを言っておきましょう。
安心出来ません(笑)。
ええとですね、明らかにANSI Common LispでのCLOS的な話書いてるよな、ってのがこちらの印象でした。
ちょっとGaucheのそのページに沿って見てみますか。
CL-USER> (class-of 50)
#<BUILT-IN-CLASS FIXNUM>
CL-USER> (class-of 3.14)
#<BUILT-IN-CLASS SINGLE-FLOAT>
CL-USER> (class-of 1/2)
#<BUILT-IN-CLASS RATIO>
CL-USER> (class-of "たけやぶやけた")
#<BUILT-IN-CLASS SB-KERNEL::SIMPLE-CHARACTER-STRING>
CL-USER>
これがANSI Common Lispでの動作で、そもそもclass-ofってのがCommon Lispの関数なんですよ。
Function CLASS-OF:
http://www.lispworks.com/documentation/lw50/CLHS/Body/f_clas_1.htm
ANSI Common Lispでのクラス定義は以下のようにして行います。
CL-USER> (defclass <2d-point> () (x y))
#<STANDARD-CLASS <2D-POINT>>
CL-USER>
defclass:
http://www.lispworks.com/documentation/lw50/CLHS/Body/m_defcla.htm#defclass
インスタンス生成にはmake-instance総称関数を使用します。
Standard Generic Function MAKE-INSTANCE:
http://www.lispworks.com/documentation/lw50/CLHS/Body/f_mk_ins.htm#make-instance
CL-USER> (defparameter a-point (make-instance '<2d-point>))
A-POINT
CL-USER>
a-pointには何の値も与えられていないので、x座標の値を10.0、y座標の値を20.0に変更してみます。アクセサ
関数はslot-valueです。
Function SLOT-VALUE:
http://www.lispworks.com/documentation/lw50/CLHS/Body/f_slt_va.htm#slot-value
CL-USER> (setf (slot-value a-point 'x) 10.0)
10.0
CL-USER> (setf (slot-value a-point 'y) 20.0)
20.0
CL-USER>
ANSI Common Lisp の setf マクロは、Scheme の set! と違ってデータの内部構造まで触れるので、アクセサさ
え与えれば汎用的に使えます。従って、Gaucheのようにslot-set!と言う手続きを別定義する必要はありません。
構文的には以下のようにして、スロットを書き換えます。
(setf (slot-value インスタンス名 スロット名) 値)
つまり、slot-valueがアクセサである以上、スロットの値を参照するにはそのままslot-valueを用いれば良いの
です。
CL-USER> (slot-value a-point 'x)
10.0
CL-USER> (slot-value a-point 'y)
20.0
CL-USER>
<2d-point>型のインスタンスと移動量dx, dyの3つを引数にとるmove-by!メソッドを定義してみます。
CL-USER> (defmethod move-by! ((p <2d-point>) dx dy)
(incf (slot-value p 'x) dx)
(incf (slot-value p 'y) dy))
STYLE-WARNING: Implicitly creating new generic function MOVE-BY!.
#<STANDARD-METHOD MOVE-BY! (<2D-POINT> T T) {B657FF1}>
CL-USER>
move-by!メソッドはincfマクロを使い、 <2d-point>インスタンスpのx, yスロットをそれぞれdx, dyだけ増加さ
せます。
CL-USER> (slot-value a-point 'x)
15.0
CL-USER> (slot-value a-point 'y)
22.0
CL-USER>
a-pointのx座標とy座標がそれぞれ指定されただけ動いてるのが分かると思います。
とまあ、ここで止めておきますが(あとは大体同じなんでご自分で試してみてください)、Gaucheの設計がどう、
と言うより殆どCLOSの解説なんですよ。もっと言うと、設計的に踏み込むと、ネイティヴにCLOSっぽいOOPをサポ
ートする為にそう言う設計にしたのか。
いずれにせよ、この辺はANSI Common Lispを扱うのなら、別に驚くような話でも無いんです。この辺の機能は全
てANSI Common Lispから借りてきています。
- 元ねた:
- 2491 Re. 2490 Re. 2489 Gauche
- フォローアップ: