Next: 3.4 マクロ定義用手続き
Up: 3 マクロ機能の追加
Previous: 3.2 マクロの展開
たとえば,and をマクロとして定義してみます.
(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))))
generated through LaTeX2HTML. M.Inaba 平成18年5月6日