next up previous
Next: 3.4 マクロ定義用手続き Up: 3 マクロ機能の追加 Previous: 3.2 マクロの展開

3.3 マクロの定義

たとえば,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日