Collision with syntax-rules identfiers and global names

53 views Asked by At

I have really edge case with syntax-rules. I'm trying to execute the let-values macro (it's from R7RS spec, but I've replaced string literals with identifiers):

(define-syntax let-values
  (syntax-rules (bind mktmp)
    ((let-values (binding ...) body0 body1 ...)
     (let-values bind
       (binding ...) () (begin body0 body1 ...)))
    ((let-values bind () tmps body)
     (let tmps body))
    ((let-values bind ((b0 e0) binding ...) tmps body)
     (let-values mktmp b0 e0 () (binding ...) tmps body))
    ((let-values mktmp () e0 args bindings tmps body)
     (call-with-values
         (lambda () e0)
       (lambda args
         (let-values bind
           bindings tmps body))))
    ((let-values mktmp (a . b) e0 (arg ...) bindings (tmp ...) body)
     (let-values mktmp b e0 (arg ... x) bindings (tmp ... (a x)) body))
    ((let-values mktmp a e0 (arg ...) bindings (tmp ...) body)
     (call-with-values
         (lambda () e0)
       (lambda (arg ... . x)
         (let-values bind bindings (tmp ... (a x)) body))))))

Together with SRFI-210 I have a collision between the bind identifier and function named bind:

(define (bind obj . transducers)
  (apply bind/list (list obj) transducers))

To make SRFI-210 work with my Scheme implementation I've removed the check for the identifiers to not exist in scope. But it was a mistake. Since According to Gauche syntax-rules docs this should not work:

(define-syntax if+
  (syntax-rules (then else)
    [(_ test then expr1 else expr2) (if test expr1 expr2)]))

(let ((else #f))
  (if+ (even? x) then (/ x 2) else (/ (+ x 1) 2)))

This doesn't work in the Scheme implementation I've tested (Kawa, Guile, Chicken, Chez) it only works in Gambit.

So the question is how the bind symbol should work in the let-value hygienic macro when there is a global name bind?

I've tested this:

(define else #f)
(let ((el_se #f) (x 10))
  (print (if+ (even? x) then (/ x 2) else (/ (+ x 1) 2))))

And it works for all tested implementations (ignoring Gambit where it works the same).

EDIT: I was looking at answer to this question: Introducing a Named Variable with Syntax Rules with this quote from linked paper:

Hygienic macros cannot expand in referentially-opaque code: if a macro expansion introduces a free identifier, the identifier refers to the binding occurrence which was in effect when the macro was defined rather than when the macro was expanded.

But this makes no difference in Scheme implementations I've tested.

(define else #f)

(define-syntax if+
  (syntax-rules (then else)
    ((_ test then expr1 else expr2) (if test expr1 expr2))))

(let ((el_se #f) (x 10))
  (print (if+ (even? x) then (/ x 2) else (/ (+ x 1) 2))))
0

There are 0 answers