(setf (get 'and 'scheme-macro) #'(lambda (&rest args) (cond ((null args) 't) (t `(if ,(car args) (and ,@(cdr args)))))))というように,与えられた引数(args)によって,場合を分け,もう一度評価さ れるような形を返すクロージャとして定義します. これを展開すると,
<cl> (scheme-macro-expand '(and a)) (IF A (AND)) <cl> (scheme-macro-expand '(and)) T <cl> (scheme-macro-expand '(and a nil)) (IF A (AND NIL)) <cl> (scheme-macro-expand '(and nil)) (IF NIL (AND))という具合になります. 他のマクロの例として,define, letを考えてみます. defineは関数と変数の値の両方に利用できるマクロです. defineの第一引数がシンボルであればシンボルの値定義を行ないます. defineの第一引数がリストであれば関数の定義となります.
(define a b) -> (set! a b)で結果がa (define (a x) body) -> (set! a (lambda (x) body))defineの定義は,
(setf (get 'define 'scheme-macro) #'(lambda (name &rest body) (if (atom name) `(begin (set! ,name ,@body) ',name) `(define ,(car name) (lambda ,(cdr name) ,@body)))))つまり, letはlispでのletと同じ働きをもつものです.
(setf (get 'let 'scheme-macro) #'(lambda (bindings &rest body) `((lambda ,(mapcar #'car bindings) ,@body) ,@(mapcar #'cadr bindings))))