这似乎有效,它是一个宏,可以根据扩展的次数扩展到连续的整数.
;; Library (test macro-state)
(library
(test macro-state)
(export get-count incr-count)
(import (rnrs))
(define *count* 0)
(define (get-count) *count*)
(define (incr-count) (set! *count* (+ *count* 1)))
)
;; Program
(import (rnrs) (for (test macro-state) expand))
(define-syntax m
(lambda (x)
(syntax-case x ()
((m) (begin (incr-count) (datum->syntax #'m (get-count)))))))
(write (list (m) (m) (m)))
(newline)
;; prints (1 2 3)
Run Code Online (Sandbox Code Playgroud)
但它对我来说很笨拙,因为宏状态*count*和宏m本身在不同的模块中.有没有更好的方法在r6rs中执行此操作,最好是不将两个模块的实现分开?
编辑
我应该说清楚,尽管这个例子只是一个宏,但实际上我正在寻找一种在多个宏需要共享状态时有效的方法.
您可以使宏变换器的状态为本地:
(define-syntax m
(let ()
(define *count* 0)
(define (get-count) *count*)
(define (incr-count) (set! *count* (+ *count* 1)))
(lambda (x)
(syntax-case x ()
((m) (begin (incr-count) (datum->syntax #'m (get-count))))))))
Run Code Online (Sandbox Code Playgroud)
编辑添加:在Racket中,你也可以这样做:
(begin-for-syntax
(define *count* 0)
(define (get-count) *count*)
(define (incr-count) (set! *count* (+ *count* 1))))
(define-syntax m
(lambda (x)
(syntax-case x ()
((m) (begin (incr-count) (datum->syntax #'m (get-count)))))))
Run Code Online (Sandbox Code Playgroud)
但我不认为R6RS有任何对应的东西begin-for-syntax.