guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Breaking hygiene with syntax-rules?


From: Dr. Arne Babenhauserheide
Subject: Re: Breaking hygiene with syntax-rules?
Date: Fri, 11 Aug 2023 07:07:17 +0200
User-agent: mu4e 1.10.5; emacs 29.0.92

Walter Lewis via General Guile related discussions <guile-user@gnu.org> writes:

> (define-syntax unhygienic
>   (syntax-rules ()
>     ((_ the-pair fetch)
>      (begin
>        (define the-head (car the-pair))
>        (define (fetch) the-head)))))
>
> (unhygienic '(1) fetch1)
> (unhygienic '(2) fetch2)
>
> (fetch1)
>
> ;; => 2

I just tested this and see the same problem:

(unhygienic '(a) name1)
(unhygienic '(b) name2)
(name1) ;; => b
(name2) ;; => b

So it’s reproduced. Thank you for the minimal example!

> It seems that the second call to unhygienic shadows the previous
> definition of the-head. I expected syntax-rules to generate fresh
> names for it each time.
>
> Is this expected, and if so, is there any way to generate an internal
> definition using syntax-rules? For my case, I was writing a macro to
> generate SRFI-9 record definitions, but I noticed some of the getters
> and setters which I intended to be private were shadowing each other.

I did not expect this.

To track this:

(define-syntax unhygienic
  (syntax-rules ()
    ((_ the-pair fetch)
     (begin
       (define the-head (car the-pair))
       (define (the-proc) the-head)
       (define (fetch) the-head)
       (display the-proc)))))

(display the-head)
;; => error Unbound variable: the-head (step out of the debugger with C-d)
(unhygienic '(a) name1)
;; => #<procedure the-proc-1d2f8a1cb6ff0af6 ()> (the proc has a long suffix, 
looks good)
(display the-head)
;; => error: Unbound variable: the-head (looks good?)
(name1) ;; => a
(unhygienic '(b) name2)
;; #<procedure the-proc-1d2f8a1cb6ff0af6 ()> (the suffix of the proc is the 
same as for the one in a?)
(name1) ;; => b

Maybe this is just, because the procedure is *the same*?
Let’s use fetch in the-proc:

(define-syntax unhygienic
  (syntax-rules ()
    ((_ the-pair fetch)
     (begin
       (define the-head (car the-pair))
       (define (the-proc) fetch)   
       (define (fetch) the-head)
       (display the-proc)))))
(unhygienic '(a) name1)
;; => #<procedure the-proc-7f18b8db60e30e7 ()>
(unhygienic '(b) name2)
;; => #<procedure the-proc-ca383a2334aaa56 ()>
(name1)
;; => b


Now the proc is no longer the same, but the variable still collides.

Auto-completion in the REPL
the-head-<TAB>
;; => the-head-3f6c11022fffe02

the-head also has a suffix, as it should have, but there is only one.

Does the counter go wrong?

One more check:

(define-syntax unhygienic
  (syntax-rules ()
    ((_ the-pair fetch)
     (begin
       (define the-head fetch)
       (define (the-proc) fetch)   
       (define (fetch) the-head)
       (display the-proc)))))

Now using fetch in the-head I get two different variables in the shell.

Maybe detection of external data is missing that the-pair is external?

Best wishes,
Arne
-- 
Unpolitisch sein
heißt politisch sein,
ohne es zu merken.
draketo.de

Attachment: signature.asc
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]