マクロの動作(1)

(defmacro m1 () (1+ 1))
(m1)
|
2

(macroexpand'(m1))
|
2
;展開時に評価される。


(defmacro m2 () '(1+ 1))
(m2)
|
2

(macroexpand'(m2))
|
(1+ 1)
;これが実行時に評価される。

;参考
'hoge = (quote hoge)
|
hoge


(defmacro m3 () ''(1+ 1))
(m3)
|
(1+ 1)
;展開しても評価されていない。

(macroexpand'(m3))
|
'(1+ 1)


(defmacro m4 () '''(1+ 1))
(m4)
|
'(1+ 1)

(macroexpand'(m4))
|
''(1+ 1)

;結局、展開時に1つ、評価時に1つ quote が減る(unquoteされる)。


(defun f1 ()
  (list '1+ 1))
(f1)
|
(1+ 1)


(defmacro m5 ()
  `(list ,(m1) ,(m2) ,(m3) ,(m4) ,(f1)))
(m5)
|
(2 2 2 (1+ 1) 2)

(macroexpand'(m5))
|
(list 2 2 (1+ 1) '(1+ 1) (1+ 1))

;f1はm3と同じ。

;参考
'hoge = `hoge
|
hoge
; ` (backquote) は基本的にはquoteと同じ。

``hoge
|
'hoge

`(,(+ 1 2))
|
(3)
; , (comma) の後ろが評価される。

`(,@(+ 1 2))
|
3

`'(,@(+ 1 2))
|
'3

'`(,@(+ 1 2))
|
(+ 1 2)

``(,@(+ 1 2))
|
(+ 1 2)

`(,@'(+ 1 2))
|
(+ 1 2)

`(',@(+ 1 2))
|
((quote . 3))

; ,@ (comma at) の後ろは評価されてから親のリストにappend(or nconc)される。

``(,@,@'(+ 1 2))
|
(append + 1 2)
; 入れ子になったときの取り扱いはややこしい。

'`(,@'(,@ nil))
|
'nil
;この結果はxyzzyの仕様がまずいことを示している。何が問題かわかるだろうか。


``(nil ,@ nil (nil ,@'(nil nil) ,@'(nil ,@ nil)) nil)
|
(cons 'nil (append nil (cons (cons 'nil (append '(nil nil) '(nil))) '(nil))))


`(,'@(+ 1 2))
|
(@ (+ 1 2))
; , と @ は離さない。


(defmacro m6 ()
  (macrolet ((m () ``(list (m1) (m2) ,(m3) ,,(m4) ,(f1))))
	(m)))
(m6)
|
(2 2 2 2 2)

(macroexpand'(m6))
|
(list (m1) (m2) (1+ 1) (1+ 1) (1+ 1))
;評価されるタイミングを合わせる。変数に展開されるときは重要である。