マクロ


*executing-macro*

Type: Variable
Package: editor
File: cmds.l
マクロを実行中か否かを返します。 
  t    マクロを実行中
  nil  マクロを実行中ではない 

[ Intro | 目次 | 索引 | 目的別 | マクロ ]

call-last-kbd-macro

Type: Function
Arguments: call-last-kbd-macro &optional (ARG 1)
Package: editor
File: kbdmacro.l
start-kbd-macro/end-kbd-macroで登録したキーボードマクロを実行します。 
[ツール(T)]-[キーボードマクロおまけ(O)]-[保存]したキーボードマクロは、 
[ツール(T)]-[キーボードマクロおまけ(O)]-[読み込み]で後から選択することが可能です。 

[ Intro | 目次 | 索引 | 目的別 | マクロ ]

defmacro

Type: Macro
Arguments: defmacro NAME (&rest LAMBDA-LIST) &body BODY
Package: lisp
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
SeeAlso: ``'(backquote)
[ Intro | 目次 | 索引 | 目的別 | マクロ ]

macro-function

Type: Function
Arguments: macro-function SYMBOL
Package: lisp
File: builtin.l
SYMBOLがマクロか否かを返します。マクロの場合にはその内容を返します。 
使用例: 
  (macro-function 'car)
  =>nil

  (macro-function 'when)
  =>(macro (lisp::test &body lisp::body)
         (block when (list 'if lisp::test (cons 'progn lisp::body))))

SeeAlso: fboundp
SeeAlso: boundp
[ Intro | 目次 | 索引 | 目的別 | マクロ ]

macroexpand

Type: Function
Arguments: macroexpand FORM &optional ENV
Package: lisp
File: builtin.l
フォームがどのようにマクロ展開されるかを返します。 
マクロの展開され方を確認するのに役立ちます。 

使用例: 
  ;;; マクロM2を定義してどのように展開
  (defmacro M2 (&rest args)
      `(progn
         (m-setup) ,@args (m-cleanup)))
  (macroexpand '(M2 (insert "Begin") (insert "End")))
  => (progn (m-setup) (insert "Begin") (insert "End") (m-cleanup))

SeeAlso: defmacro
[ Intro | 目次 | 索引 | 目的別 | マクロ ]

macroexpand-1

Type: Function
Arguments: macroexpand-1 FORM &optional ENV
Package: lisp
File: builtin.l
macroexpandに似ていますが、展開されるレベルが1レベルで終わるところが違います。 
自作のマクロなどがどう展開されるのか調べるときに便利です。 

使用例:
  (defmacro my-macro ()
    `(dotimes (x 10)))
  というマクロがあるとき 
  
  (macroexpand '(my-macro))
  => (block nil (let* ((x 0) (#1=#:count 10)) (lisp::*loop (if (>= x #1#) (return (progn 'nil))) (tagbody) (setq x (+ x 1)))))
  とmy-macro展開後のdotimesまで(実際はdotimesを展開後さらにdo*を展開)が 
  再帰的に展開されますが、 

  (macroexpand-1 '(my-macro))
  => (dotimes (x 10))
  と、my-macroだけが展開されます。 

SeeAlso: macroexpand
[ Intro | 目次 | 索引 | 目的別 | マクロ ]

macrolet

Type: Special Form
Arguments: macrolet ({(NAME LAMBDA-LIST {declaration}* [doc-string] {FORM}*)}*) {FORM}*
Package: lisp
File: builtin.l
defmacroの局所版です。 

SeeAlso: defmacro
SeeAlso: flet
[ Intro | 目次 | 索引 | 目的別 | マクロ ]

``'(backquote)

Type: Misc
Arguments: form
Package: ???
注:タイプはリードマクロなんですが・・・
  info-modokiでどうしようか悩んでしまいます。 

``'(逆引用符(backquote))はリストをquoteします。ただし、特別な標識 `,' 
及び `,@' を用いることで、リストの要素を選択的に評価することができます。 

使用例: 
  ;;; 逆引用符を使用してリストを作成
  (setq f0 '(0 1 2 3))         =>  (0 1 2 3)  
  (setq f1 `(0 1 2 3))         =>  (0 1 2 3)
  (setq f2 `(4 5 ,(car f1)))   =>  (4 5 0)
  (setq f3 `(6 7 ,(cdr f1)))   =>  (6 7 (1 2 3))
  (setq f4 `(8 9 ,@(cdr f1)))  =>  (8 9 1 2 3)

参考: 
  --- elisp-jpより引用 ---
  
  逆引用符の引数の中に特別な標識`,'を入れると、その値は定数でないことを表
  わします。逆引用符は`,'の引数を評価し、リスト構造にその値を入れます。 
  
     (list 'a 'list 'of (+ 2 3) 'elements)
          => (a list of 5 elements)
     `(a list of ,(+ 2 3) elements)
          => (a list of 5 elements)
  
  特別な標識`,@'を用いることで、評価した値を結果のリストに"組み込む
  (splice)"こともできます。組み込まれたリストの要素は、結果のリストのほか 
  の要素と同じレベルの要素になります。``'を使わない等価なコードは、往々に
  して読みにくくなります。例をあげます。 
     (setq some-list '(2 3))
          => (2 3)
     (cons 1 (append some-list '(4) some-list))
          => (1 2 3 4 2 3)
     `(1 ,@some-list 4 ,@some-list)
          => (1 2 3 4 2 3)

[ Intro | 目次 | 索引 | 目的別 | マクロ ]