マクロ
Type: Variable
Package: editor
File: cmds.l
マクロを実行中か否かを返します。
t マクロを実行中
nil マクロを実行中ではない
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)]-[読み込み]で後から選択することが可能です。
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)
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
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
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
Type: Special Form
Arguments: macrolet ({(NAME LAMBDA-LIST {declaration}* [doc-string] {FORM}*)}*) {FORM}*
Package: lisp
File: builtin.l
defmacroの局所版です。
SeeAlso: defmacro
SeeAlso: flet
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)