プログラミング Gauche をよむ

  • Gauche プログラマは慣習として, のように<と>で囲んだ名前をクラス名として使用する
  • メタクラスを複数持ちたい場合,メタクラスを持つクラスを作成してそれを継承する
  • 総称関数はオブジェクト

ふつうのRuby プログラマGauche をやるときは,
オブジェクトのところから読むとわかりやすいかな?
と思ってみたりなどした.

  • 総称関数 initialize
  • すべてがオブジェクト

p255

;; <logger-generic> の適用
(define-class <logger-generic> (<generic>)
  ((logging :init-value #t)))
(define-generic add :class <logger-generic>)
(define-method apply-generic ((gf <logger-generic>) args)
  (when (ref gf 'logging)
        (format #t "args: ~s\n" args)
        (let ((return-value (next-method)))
          (format #t "result: ~s\n" return-value)
          return-value)))
(define-method add ((num1 <number>) (num2 <number>))
  (+ num1 num2))

(add 3 4)

;; <profiler-generic> の適用
(use gauche.time)
(define-class <profiler-generic> (<logger-generic>)
  ((counter :init-value 0)
   (time    :init-form (make <real-time-counter>))))
(define-generic sub :class <profiler-generic>)
(define-method apply-generic ((gf <profiler-generic>) args)
  (inc! (ref gf 'counter))
  (with-time-counter (ref gf 'time) (next-method)))
(define-method sub ((num1 <number>) (num2 <number>))
  (- num1 num2))
(define-method get-profile ((gf <profiler-generic>))
  (format #t "~s: ~d times called and spent time ~d\n"
          (ref gf 'name) (ref gf 'counter) (time-counter-value (ref gf 'time))))
(define-method init-profile ((gf <profiler-generic>))
  (set! (ref gf 'counter) 0)
  (set! (ref gf 'time) (make <real-time-counter>)))

(use srfi-1)
(set! (ref sub 'logging) #f)
(init-profile sub)
(define val (with-output-to-string
              (lambda () (map sub
                              (iota 10000 100 3)
                              (iota 10000 100 5)))))
(get-profile sub)
(format #t "val: ~s\n" val)