thanks for the replies.
that makes sense, but implies that both gambit and bigloo (see other reply) are using unsafe macro expansion. which seems like crazy talk - why would they purposefully make code unreliable?
as it happens, i am looking at rewriting the code with vectors, so will lose the values/receive code.
andrew
Date: Sat, 18 Aug 2007 23:29:19 -0400 (CLT) From: "andrew cooke" andrew@acooke.org
(define-syntax bad (syntax-rules () ((_ (arg1 ...) (arg2 ...)) (receive (a b c) (values arg1 ...) (newline) (write (list arg2 ...))))))
(receive (a b c) (values 1 2 3) (bad (7 8 9) (a b c)))
This displays (7 8 9) when arg2 should be (1 2 3) (the value of a b c in the calling code, not the value in "bad").
This is because Gambit runs two macro expanders over the code: the SYNTAX-CASE expander (hygienic), and then the evaluator's own non-hygienic expander. To SYNTAX-CASE, RECEIVE looks like a variable reference, not a binding form, so it doesn't recognize that A, B, and C are to be bound to distinct variables in the two distinct uses of RECEIVE. Then the evaluator's non-hygienic expander actually expands the RECEIVE to a call to CALL-WITH-VALUES (or the ridiculously octothorped version thereof), and the variables are captured.
Try this before running the example:
(define-syntax receive (syntax-rules () ((RECEIVE bvl expression body0 body1 ...) (CALL-WITH-VALUES (LAMBDA () expression) (LAMBDA bvl body0 body1 ...)))))
Then RECEIVE will be a hygienic macro, and the SYNTAX-CASE expander should rename the variables introduced by BAD accordingly.