42 lines
1.2 KiB
Plaintext
42 lines
1.2 KiB
Plaintext
|
(define-syntax color (syntax-rules () ((color) 'green)))
|
||
|
|
||
|
(define-syntax with-blue
|
||
|
(lambda (exp r c)
|
||
|
`(,(r 'let-syntax) ((color (,(r 'syntax-rules) ()
|
||
|
((color) 'blue))))
|
||
|
. ,(cdr exp))))
|
||
|
|
||
|
(with-blue (color))
|
||
|
|
||
|
;;; This has a problem -- WITH-BLUE is not hygenic:
|
||
|
(let ((color (lambda () 'foo)))
|
||
|
(with-blue (color)))
|
||
|
|
||
|
=> blue
|
||
|
|
||
|
;;; Let's fix this by adding a layer of indirection --
|
||
|
;;; 1. (color) ==> (hidden-color)
|
||
|
;;; 2. with-blue frobs the definition of *our* hidden-color
|
||
|
|
||
|
(define-syntax hidden-color (lambda (exp r c) `(,(r 'quote) green)))
|
||
|
(define-syntax color (lambda (exp r c) `(,(r 'hidden-color))))
|
||
|
|
||
|
(define-syntax with-blue
|
||
|
(lambda (exp r c)
|
||
|
`(,(r 'let-syntax)
|
||
|
((,(r 'hidden-color) (,(r 'syntax-rules) ()
|
||
|
((,(r 'hidden-color)) (,(r 'quote) blue)))))
|
||
|
. ,(cdr exp))))
|
||
|
|
||
|
;;; Without all the renaming, the above is
|
||
|
;;; (let-syntax ((hidden-color (syntax-rules () ((hidden-color 'blue)))))
|
||
|
;;; body ...)
|
||
|
;;; where *all* symbols on the first line are renamed, *including*
|
||
|
;;; hidden-color, so we should be redefining the same hidden-color
|
||
|
;;; to which (color) expands.
|
||
|
|
||
|
;;; It doesn't work:
|
||
|
(with-blue (color))
|
||
|
=> green
|
||
|
|