Opened 3 years ago
Closed 3 years ago
#1804 closed defect (invalid)
compare doesn't compare if name is already bound
| Reported by: | Idiomdrottning | Owned by: | |
|---|---|---|---|
| Priority: | major | Milestone: | someday |
| Component: | expander | Version: | 5.2.0 |
| Keywords: | Cc: | ||
| Estimated difficulty: | medium |
Description
(define-syntax frob-bad
(ir-macro-transformer
(lambda (exp inject compare)
(let ((body (cdr exp)))
`',(let desc ((friends '()) (body body))
(cond
((null? body)
friends)
((pair? body) (append (desc friends (car body)) (desc friends (cdr body))))
((any (cut compare body <>) '(x y z rest args))
(cons (strip-syntax body) friends))
(else '())))))))
(equal?
((lambda (x) (frob-bad (reverse x))) 'foo) ; unexpected behavior. Since x is bound in the scope.
((lambda (p) (frob-bad (reverse x))) 'foo) ; expected behavior. Since x is not bound in the scope.
)
(define-syntax frob-good
(ir-macro-transformer
(lambda (exp inject compare)
(let ((body (cdr exp)))
`',(let desc ((friends '()) (body body))
(cond
((null? body)
friends)
((pair? body) (append (desc friends (car body)) (desc friends (cdr body))))
((memq (strip-syntax body) '(x y z rest args))
(cons (strip-syntax body) friends))
(else '())))))))
(equal?
((lambda (x) (frob-good (reverse x))) 'foo) ; working workaround by eq? after strip-syntax instead of compare
((lambda (p) (frob-good (reverse x))) 'foo))
Note: See
TracTickets for help on using
tickets.

This works as expected - you're trying to compare unhygienically against
x, so you should either use(inject '(x y z rest args))for the comparison infrob-bad, or usestrip-syntaxlike you're doing infrob-good.The comparison procedure works analogously to explicit renaming macros, but using implicit renaming. So when you compare against a value, it takes the value you pass it and implicitly renames it before comparing, just like it would've done on the output.