[前][次][番号順一覧][スレッド一覧][生データ]

langsmith:107

From: Shiro Kawai <shiro lava.net>
Date: Wed, 25 Aug 2004 11:27:05 +0900
Subject: [langsmith:107] Re: パターン支援言語? ご意見拝聴

問題を理解するために、ちょっとMOPを使って書いてみました。実装はGaucheです。
もとのWさんの 
  Aggregate P, A, B
が、
  (define-aggregate P A B)
になります。
コード自体は40行ほどですが、実行例もついているので、まとめて下に貼っておきます。

実行とコンパイルのフェーズがC++ほど分離していないので
クラス再定義を明示的に呼び出したりしてますが、実装の詳細は本筋
ではないと思うので、ユーザから見た使用感についてコメントします。

Aggregate文のメリットは関係性を別に管理できることだと思うの
ですが、シンプルな例だとやはりメリットが見えなさそうです。
今回の例の場合、Bookの定義を読む人は当然Publisherがあることを
期待しますが、それはBookの定義には無くて、Aggregate文の方を
見ないといけませんよね。そういう点、本質的に密な関係に
適用するよりは、後付けの補助的な関係に適用すると良さそうに
思えました。デバッグ情報とか、あるいは既存のBookクラスライブラリ
に対して、自分の書棚情報をかぶせるとか。

そのようなAOP的な使い方をするなら、結構応用範囲はあるように
思えます。m-to-nにした場合の一貫性の確保なども、展開したコードに
含めることができるでしょう。(下の例では、parentが変わった時に
古いparentからchildの情報を除いていますが、似たような要領で
実装できるのではないかと思います---その部分をユーザ拡張可能に
するには、関係性の変更というメソッドをオーバライド可能なように
しておけば良いと思います。)

あと記述面で欲しいなと思ったのは、逆方向ポインタの名前指定とか
(book -> authorへのポインタはauthored-byにしたい、とか)。

ただ、Wさんもおっしゃっているように、本当にこういうのが力を
発揮しそうなのは3つ以上のクラスが絡んでくる時のように思えます。

--shiro



以下、コード:

=====================
;;
;; define-aggregate using MOP
;;
(use srfi-1)

(define-class <aggregatable-meta> (<class>)
  ())

(define-method create-aggregate (name
                                 (container <aggregatable-meta>)
                                 (contained <aggregatable-meta>))
  (let ((new-container (apply make <aggregatable-meta>
                              :name   (class-name container)
                              :supers (class-direct-supers container)
                              :slots `((,name :init-value ())
                                        ,@(class-slots container))
                              :defined-modules (ref container 'defined-modules)
                              (ref container 'initargs)))
        (new-contained (apply make <aggregatable-meta>
                              :name   (class-name contained)
                              :supers (class-direct-supers contained)
                              :slots `((,(string->symbol #`",|name|-parent")
                                        :init-value #f)
                                       ,@(class-slots contained))
                              :defined-modules (ref contained 'defined-modules)
                              (ref contained 'initargs)))
        )
    (redefine-class! container new-container)
    (redefine-class! contained new-contained)
    (values new-container new-contained)))

(define-macro (define-aggregate name container contained)
  (let ((parent-slot (string->symbol #`",|name|-parent"))
        (adder       (string->symbol #`",|name|-add!"))
        (parent      (gensym))
        (child       (gensym))
        )
    `(begin
       (set!-values (,container ,contained)
                    (create-aggregate ',name ,container ,contained))
       (define-method ,adder ((,parent ,container) (,child ,contained))
         (cond ((ref ,child ',parent-slot)
                => (lambda (old-parent)
                     (update! (ref old-parent ',name)
                              (cut delete! ,child <>)))))
         (push! (ref ,parent ',name) ,child)
         (set!  (ref ,child ',parent-slot) ,parent)))
    ))

;;
;; 実行例
;;

;; クラス定義
(define-class <publisher> ()
  ((name    :init-keyword :name)
   (address :init-keyword :address))
  :metaclass <aggregatable-meta>)

(define-class <book> ()
  ((title   :init-keyword :title)
   (pages   :init-keyword :pages))
  :metaclass <aggregatable-meta>)

(define-class <author> ()
  ((name    :init-keyword :name))
  :metaclass <aggregatable-meta>)

;; 関係の定義
(define-aggregate books <publisher> <book>) ;; 出版リスト
(define-aggregate authoring <author> <book>) ;; 著作本リスト
(define-aggregate dedicated-authors <publisher> <author>) ;; 専属契約


;; for convenience
(define-method write-object ((pub <publisher>) out)
  (format out "#<publisher ~s>" (ref pub 'name)))
(define-method write-object ((book <book>) out)
  (format out "#<book ~s>" (ref book 'title)))
(define-method write-object ((author <author>) out)
  (format out "#<author ~s>" (ref author 'name)))


;; オブジェクトの作成
(define p0 (make <publisher>
             :name "Lambda Publishing, Inc."
             :address "1357 Lambda Blvd. Ste. 246, Boston MA 10031"))
(define p1 (make <publisher>
             :name "OOBooks, LLC"
             :address "2345 Object Av., Palo Alto CA 93029"))
(define a0 (make <author> :name "Pur E. Functional"))
(define a1 (make <author> :name "Prag M. Atist"))

(define b0 (make <book>
             :title "The Art of Laziness"
             :pages 128))
(define b1 (make <book>
             :title "Functional Recipes"
             :pages 256))
(define b2 (make <book>
             :title "On Objects"
             :pages 512))

;; 関係性の初期化
(books-add! p0 b0)
(books-add! p0 b1)
(books-add! p1 b2)
(authoring-add! a0 b0)
(authoring-add! a0 b1)
(authoring-add! a1 b2)
(dedicated-authors-add! p0 a0)
(dedicated-authors-add! p1 a1)

#|
;;; 確認
(ref p0 'books)
;; => (#<book "Functional Recipes"> #<book "The Art of Laziness">)
(ref p1 'books)
;; => (#<book "On Objects">)
(ref b0 'books-parent)
;; => #<publisher "Lambda Publishing, Inc.">
(ref a0 'authoring)
;; => (#<book "Functional Recipes"> #<book "The Art of Laziness">)
(ref b2 'authoring-parent)
;; => #<author "Prag M. Atist">
(ref p1 'dedicated-authors)
;; => (#<author "Prag M. Atist">)

;;; 衝撃の移籍!
(dedicated-authors-add! p0 a1)

(ref p0 'dedicated-authors)
;; => (#<author "Prag M. Atist"> #<author "Pur E. Functional">)
(ref p1 'dedicated-authors)
;; => ()
|#

=====================
コード終り。


--
ML: langsmith quickml.atdot.net
使い方: http://www.atdot.net/~ko1/quickml

[前][次][番号順一覧][スレッド一覧][生データ]

        96 2004-08-21 23:23 [ttn3w7u2fs mx6.ttcn.] パターン支援言語? ご意見拝聴           
        97 2004-08-22 13:13 ┗[takuo aya.or.jp     ]                                       
        98 2004-08-22 22:34  ┗[ttn3w7u2fs mx6.ttcn.]                                     
        99 2004-08-23 10:12   ┗[takuo aya.or.jp     ]                                   
       100 2004-08-23 22:47    ┗[ttn3w7u2fs mx6.ttcn.]                                 
       101 2004-08-23 23:29     ┣[eclipse cspc.jp     ]                               
       102 2004-08-24 22:38     ┃┗[ttn3w7u2fs mx6.ttcn.]                             
       103 2004-08-25 00:11     ┃ ┣[eclipse cspc.jp     ]                           
->     107 2004-08-25 11:27     ┃ ┗[shiro lava.net      ]                           
       108 2004-08-25 13:14     ┃  ┗[shiro lava.net      ]                         
       105 2004-08-25 00:30     ┗[takuo aya.or.jp     ]                               
       110 2004-08-30 22:29      ┗[ttn3w7u2fs mx6.ttcn.]