関数の差し替え

profile.lispから学んだ技法。ある関数を別の関数に差し替える。clispで試した。
これを使うとCLOSの:before/:afterが関数でも使える。というか、defmethodに変えて:before/:after使ったほうがいいかもしれん。
それには、symbol-functionで取得できるシンボルに対応した関数を別のものに差し替えてやればいい。たいていは単純に差し替えるのではなくて、元の関数をラップして機能を追加することになるだろう。
なので、次のような関数を用意してやる。

(defun wrap-function(wrap fn-name)
  (let ((fn (symbol-function fn-name)))
    (setf (symbol-function fn-name)
            (funcall wrap fn))))

ほいで、parseが呼び出されるたびに"."を標準出力に出したい場合は次のようにする。

(defun report(fn)
  #'(lambda(&rest args)
      (princ ".")
      (apply fn args)))
    
(wrap-function #'report 'parse)