My attempt seems to work; give it a whirl and let me know if you
agree. The question I have is: how would one do this with
(make-fluid) instead of (gensym) so that this would work with threads?
Is it really basically just a couple of substitutions?
Here's my quick hack:
(defmacro fluid-let (binding-ls . body)
(let* ((expanded-binding-ls
(map (lambda (binding)
(append binding (list (gensym))))
binding-ls))
(initial-set!-ls
(map (lambda (binding)
`(set! ,(car binding) ,(cadr binding)))
expanded-binding-ls))
(save-set!-ls
(map (lambda (binding)
`(define ,(caddr binding) ,(car binding)))
expanded-binding-ls))
(final-set!-ls
(map (lambda (binding)
`(set! ,(car binding) ,(caddr binding)))
expanded-binding-ls)))
`(begin
,@save-set!-ls
(dynamic-wind
(lambda () ,@initial-set!-ls)
(lambda () ,@body)
(lambda () ,@final-set!-ls)))))
and now some code to test it:
(define a 2)
(define b 4)
(for-each display `(a ":" ,a " " b ":" ,b "\n"))
(fluid-let ((a (* a a))
(b (* b b)))
(for-each display `(a ":" ,a " " b ":" ,b "\n"))
(error "out of here"))
(for-each display `(a ":" ,a " " b ":" ,b "\n"))
-russ