method-missingを作ってみた

勢い余って「適用できるメソッドがなければ method-missing を呼び出す」機能を作ってみた.

(define-generic method-missing)

(define-class <method-missing-generic> (<generic>)
  ())

(define-method apply-methods ((gf <method-missing-generic>) methods args)
  (if (null? methods)
      (apply method-missing gf args)
      (next-method)))

ドキュメントがなくて推測だけど,apply-methods は(sort-applicable-methods で)ソートされた適用可能なメソッドのリストを受け取り,next-method が次のメソッドを呼び出すように設定して,メソッドを呼び出すのだろう.とにかく適用可能なメソッドがなくても apply-methods は(空リストを伴って)呼ばれるようだ.

(define-generic foo :class <method-missing-generic>)

(define-method foo ((num <number>))
  `(number ,num))

(define-method method-missing ((gf <method-missing-generic>) (str <string>) :rest args)
  `(missing ,(~ gf 'name) string ,str))

(foo 42)     ; => (number 42)
(foo "bar")  ; => (missing foo string "bar")


(define-method foo ((num <string>))
  `(string ,num))

(foo "bar")  ; => (string "bar")

呼び出すジェネリックファンクション foo は予め定義しておかないといけないので有り難みは薄い気がする.