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については勘違いがあったので削除しました。混乱させて申し訳ありません。