I may be misunderstanding hygienic macros here, but as far as I can tell I am getting variable capture.
(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").
It can be avoided by using different variable names, but that should not be necessary, right?
Thanks, Andrew
PS Gambit Version 4.0 beta 22, on Suse linux 10.2, amd64.
Afficher les réponses par date
Hi.
I may be misunderstanding hygienic macros here, but as far as I can tell I am getting variable capture.
I don't use hygienic macros either but
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").
Bigloo prints (7 8 9) and Gauche prints (1 2 3) Chicken, guile, mzscheme and petite all fail with macro error, or receive error.
I have no clue which one is correct (I don't use values either), but I guess it shows that define-macro is better :)
By the way. I think you should also tell the maintainers of the portable syntax-case about this bug, if you're sure both gambit and bigloo got it wrong (and tell the maintainer of bigloo too then).
Adrien
Adrien Pierard wrote:
Hi.
I may be misunderstanding hygienic macros here, but as far as I can tell I am getting variable capture.
I don't use hygienic macros either but
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").
Bigloo prints (7 8 9) and Gauche prints (1 2 3) Chicken, guile, mzscheme and petite all fail with macro error, or receive error.
You probably forgot to import "receive". Here is what happens in mzscheme:
(require (lib "8.ss" "srfi"))
(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)))
(1 2 3)
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.
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.
On 19-Aug-07, at 7:46 PM, andrew cooke wrote:
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?
Could you please explain what you mean by "unsafe macro expansion"?
Marc
Date: Sun, 19 Aug 2007 20:17:03 -0400 From: Marc Feeley feeley@iro.umontreal.ca
Could you please explain what you mean by "unsafe macro expansion"?
Presumably, he is referring to the non-hygienic macros like RECEIVE in the Gambit system, which are processed not by the hygienic SYNTAX-CASE expander but rather by the non-hygienic macro expander in the built-in evaluator.