s7のマクロはファーストオブジェクトで、動的に展開される。これは正しいLISPの挙動と思われるが、マクロを多用すればするほど実行速度は遅くなる。そこで、マクロを無理やり静的に展開するマクロを作った。
(define (static-expand body)
(let loop ((calls body)
(ret '()))
(if (null? calls)
(reverse ret)
(let ((next (cdr calls)))
(if (and (not (null? next)) (not (pair? next)))
(if (null? ret)
(cons (let ((l (car calls)))
(if (pair? l)
(loop l '())
l))
next)
(append (reverse (cdr ret)) (cons (car ret) next)))
(loop next
(cons (let ((call (car calls)))
(if (pair? call)
(let ((head (car call)))
(if (and (symbol? head) (defined? head (rootlet)))
(let ((_head (eval head (rootlet))))
(if (macro? _head)
(let ((_call (eval `(macroexpand ,call) (rootlet))))
(if (pair? _call)
(loop _call '())
_call))
(loop (cdr call) `(,head))))
(loop call '())))
call))
ret)))))))
(define-macro (befine args . body)
`(define ,args ,@(static-expand body)))
(define-macro (befine* args . body)
`(define* ,args ,@(static-expand body)))
使い方は、関数定義の先頭文字をdからbに変えるだけw
いじょう