Emacs Lispで関数定義を置き換える方法
Emacs Lispでは、気に入らない関数呼び出しを別な関数に置き換えることができる。たとえば、今のウィンドウに表示してほしいのに内部で switch-to-buffer-other-window を呼んでいる場合とか。
こんな場合は、letfやfletやlabelsを使えばよい。letにはlet*という亜種があるように、letfにはletf*という亜種がある。
関数定義をすげ変えるテストケースを el-expectations.el で記述してみる。
(require 'el-expectations) (require 'cl) ; (eval-when-compile (require 'cl)) でもよい (defun f (x) (* 2 x)) (defun g (x) (* 3 x)) (expectations (desc "オリジナル") (expect 4 (f 2)) (expect 6 (g 2)) (desc "関数定義を置き換える") (expect 14 (flet ((f (x) (* 7 x))) ;関数定義(置き換えも) (f 2))) (expect 6 (letf (((symbol-function 'f) (symbol-function 'g))) ;関数セルを置き換える (f 2))) (desc "元通り") (expect 4 (f 2)) (expect 6 (g 2)) )
で、switch-to-buffer-other-windowをswitch-to-bufferにすげ変える例はこんなの。評価したら switch-to-buffer が呼ばれる。
(letf (((symbol-function 'switch-to-buffer-other-window) (symbol-function 'switch-to-buffer))) (switch-to-buffer-other-window "*scratch*"))
[2009/09/19]追記
letとlabelsについては勘違いがあったので削除しました。混乱させて申し訳ありません。