Scheme:MOP:議論

Scheme:MOP:議論

MOPに関する議論,質問,その他の起点にでも.

generic-applyのカスタマイズ

ねるWiki:ねる2004/05/21 11:03:24 PDT

下のコードのように<generic>のサブクラス<wrapper-generic>を作り,<wrapper-generic>のインスタンスの総称関数に対する適用を特定化したapply-generic methodを定義することにより実現しています.これを読んでいてすこし疑問がわきました.

以下,Gauche/test/object.scmより抜粋

;;----------------------------------------------------------------
(test-section "method application customization")

;; The original example of <wrapper-generic> is presented by Alex Shinn.

(define-class <wrapper-generic> (<generic>) ())

(define-method write-object ((obj <wrapper-generic>) port)
  (format port "#<wrapper-generic ~a>" (ref obj 'name)))

(define-method object-unwrap (obj pass fail)
  (fail))

(define-method apply-generic ((gf <wrapper-generic>) args)
  (let ((methods (compute-applicable-methods gf args)))
    (if (pair? methods)
      (apply-methods gf (sort-applicable-methods gf methods args) args)
      (let loop ((ls args) (rev '()))
        (if (null? ls)
          (errorf "no applicable method for ~S with arguments ~S" gf args)
          (object-unwrap
           (car ls)
           (lambda (obj)
             (apply-generic gf (append (reverse rev) (list obj) (cdr ls))))
           (lambda () (loop (cdr ls) (cons (car ls) rev)))))))))

(define-class <ci-string> ()
  ((value :init-keyword :value)))

(define (ci-string str) (make <ci-string> :value str))

(define-method object-unwrap ((obj <ci-string>) pass fail)
  (pass (ref obj 'value)))

(define-generic concat :class <wrapper-generic>)
(define-method concat () "")
(define-method concat ((a <string>)) a)
(define-method concat ((a <string>) (b <string>))
  (string-append a b))
(define-method concat ((a <string>) (b <string>) c . rest)
  (string-append a b (apply concat c rest)))

(test* "<wrapper-generic>" "aBciIiXyZ"
       (concat (ci-string "aBc") "iIi" (ci-string "XyZ")))

--


Last modified : 2012/02/07 08:44:57 UTC