On Lisp 8章まとめ
原則的には関数を使うべきだが、マクロでないとできないことがあったり、マクロでやる方が良い場合がある。
マクロでないとできないこと
- 関数は引数を全て評価する
- マクロは引数の評価を制御できる
マクロでも引数全部を一回ずつ評価するようなものは関数と同じことになる。
(defun my-1+ (x) (+ 1 x)) (defmacro my-1+ (x) `(+ 1 ,x))
引数の評価を制御することによって、以下のようなことができるようになり、これらは関数ではできないこと。
- 変形 setf
- 変数束縛
- 条件分岐による評価 when
- 複数回の評価 while
- 呼び出し側環境を利用する 継続
- 新しい環境を包み込む let
- 関数呼び出しを節約する コンパイル時にはマクロ展開される
マクロでやる方が良い場合
例えば引数の平均を返すavgなら、関数でもマクロでも書ける。
(defun avg-func (&rest args) (/ (apply #'+ args) (length args))) (defmacro avg-mac (&rest args) `(/ (+ ,@args) ,(length args)))
関数版ではargsの値を評価してからlengthで長さを調べるが、マクロ版ではargsを評価する前にlengthで長さを調べるので効率的だという。
関数よりもマクロでやったほうがいいのは、
- 評価時の前、コンパイル時に処理してしまいたいとき
- 処理系に関らずインライン展開したいとき(関数のインライン展開をするかどうかは処理系による)