[xyzzy:03975] Re: 行番号つきラインコピー (と質問)
- Subject: [xyzzy:03975] Re: 行番号つきラインコピー (と質問)
- From: Tetsuya Kamei <kamei@xxxxxxxxxxxx>
- X-mailer: Denshin 8 Go V321.2b5
- X-yzzy-version: 0.2.0.121.1
やまもとさん、こんにちは。
Wed, 26 Jan 2000 21:51:23 +0900 の
“[xyzzy:03952] Re: 行番号つきラインコピー (と質問)”
への返事です.
| いや〜、lispは亀井さんとか逸見さんのソースだけ見ながら
| 勉強した人間なので、ちょっと根本的に、、、
マクロは 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)))
--
亀井哲弥(Tetsuya Kamei)
kamei@xxxxxxxxxxxx/JCA00343@xxxxxxxxxxx