EmacsLisp のマクロは byte-compile することで、ソースコードに埋めこまれる。マクロは defun
の代わりに defmacro
を使って書く。シンプルなマクロは、関数を書くのと変わらない。一点注意するとしたら、マクロは使われる前に定義しておくこと。
マクロの特徴の一つに、byte-compile 時に式を評価できることが挙げられる。一例として deprecated (廃止された) 関数の呼び出しを書いてみる。
関数を使う
Emacs は進化とともに廃止される関数がある。ここでは interactive-p
という関数を取り上げてみよう。この関数は、関数がコマンドとして呼ばれた時は t
を返し、関数の中から呼ばれた時は nil
を返す。しかし、Emacs 23.2 で called-interactively-p
という関数に置き換わった。
古い Emacs でも動作を保証するために、関数 called-interactively-p
が存在する時はこれを使い、存在しないなら古くからある interactive-p
を使う関数 foo-called-interactively-p
を作る。自作の EmacsLisp では called-interactively-p
や interactive-p
を直接呼ばず、 foo-called-interactively-p
を使う。
(defun foo-called-interactively-p ()
(cond
((fboundp 'called-interactively-p) (called-interactively-p 'any))
(t (interactive-p))))
この関数には気に入らない点が二つある。
- Emacs 23.2 以降でソースコードを byte-compile すると、
interactive-p
は deprecated だと警告が出る foo-called-interactively-p
を呼び出す度に、関数called-interactively-p
が存在するかチェックする
マクロを使う
foo-called-interactively-p
をマクロで書き直してみる。マクロを使うと、byte-compile 時に評価が出来るので、 called-interactively-p
が存在するか否かのチェックは byte-compile 時に行なえる。
また、マクロによって展開されたコードに (Emacs が 23.2 以降なら) interactive-p
は含まれていないので、警告も出ない。Emacs の byte-compiler が出す「本当の警告」に集中することができる。
マクロを使って書き直したコードは次のようになる:
(defmacro foo-called-interactively-p ()
(cond
((fboundp 'called-interactively-p) '(called-interactively-p 'any))
(t '(interactive-p))))
byte-compile 時に評価するコードはそのまま書いて、残すコードを quote している。
試しに macroexpand
を使って、このマクロを展開してみる (Emacs 24.4 にて評価)。結果は次の通り:
(macroexpand '(foo-called-interactively-p))
-> (called-interactively-p (quote any))
called-interactively-p を使うコードだけが残った。
あとがき
EmacsLisp では、C 言語より高度なマクロを書くことができる。使いすぎは毒だけど、適度に使えばとても便利。バッククォートと組み合わせると、更に便利になる。何か良い例題があったら中級編も書いてみたい。
ちなみに、今回紹介したコードは fcopy.el で使っている。
No comments:
Post a Comment