defmacro

Title
defmacro
Type
Macro
Arguments
defmacro NAME (&rest LAMBDA-LIST) &body BODY
Package
lisp
Section
マクロ
File
evalmacs.l
マクロを定義します。

使用例:
  ;;; cadrをマクロで定義し直した場合
  (defmacro cadr (x)
    (list 'car (list 'cdr x)))
  => cadr
  (macroexpand '(cadr y))
  => (car (cdr y))

参考:
  --- 亀井さんの説明 [xyzzy:03975] ---
  
  マクロは 2 回評価される関数みたいなものと思っていれば
  間違いないでしょう(ただし 1 回目の評価のときには引数の
  評価はされない)。ごく簡単な例をあげると、
  
    (defmacro foo ()
      '(+ 1 2))
  
  このように定義して (foo) を評価すると、1 回目の評価で
  (+ 1 2) が返り、それをさらに評価して 3 が返る、となり
  ます。引数がある場合も同様に、
  
    (defmacro bar (n)
      (list '+ 1 n))
  
    (bar 3)
    -> (+ 1 3)
    => 4
  
  となります。
  
  | (M (any1) (any2) (any3)) と呼び出すと、
  |     (progn
  |       (m-setup)
  |       (any1)
  |       (any2)
  |       (any3)
  |       (m-cleanup))
  | と呼ばれるのと同じよう動作するものはどうしたら良いですか?
  
  この場合、引数が 3 つなので、こうなります。
  
    (defmacro M (a b c)
      (list 'progn '(m-setup) a b c '(m-cleanup)))
  
    (M (any1) (any2) (any3))
    -> (progn (m-setup) (any1) (any2) (any3) (m-cleanup))
    => ?
  
  ふつ〜、引数は何個でもありだろうってなときは、通常の関
  数と同様に &rest で受けてやればいいわけですね。
  
    (defmacro M2 (&rest args)
      (append '(progn) '((m-setup)) args '((m-cleanup))))
  
    (M2 (any1) (any2) (any3))
    -> (progn (m-setup) (any1) (any2) (any3) (m-cleanup))
    => ?
  
  ちなみに、1 回目がどのように評価されているか(マクロの
  展開)を見るには macroexpand を使います。
  
    (macroexpand '(M2 (any1) (any2) (any3)))
    => (progn (m-setup) (any1) (any2) (any3) (m-cleanup))
  
  複雑なマクロ定義だと、list やら append やら cons やら 
  quote やらをごちゃごちゃ書くのがめんどくせ〜、というわ
  けでテンプレートを使うことができます。詳しい説明は面倒
  なのでしませんが(^^; 上の例をテンプレートを使って書く
  とこのようになります。
  
    (defmacro M (a b c)
      `(progn
         (m-setup)
         ,a ,b ,c
         (m-cleanup)))
  
    (defmacro M2 (&rest args)
      `(progn
         (m-setup)
         ,@args
         (m-cleanup)))
Seealso
macroexpand
``'(backquote)