Opened 4 months ago

Closed 4 months 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))

Change History (1)

comment:1 Changed 4 months ago by sjamaan

Resolution: invalid
Status: newclosed

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 in frob-bad, or use strip-syntax like you're doing in frob-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.

Note: See TracTickets for help on using tickets.