I've encountered an identifier binding order issue that only manifests in 
the REPL.  My current workaround is to use forward definitions followed by 
set!s.  I've heard rumors that the top-level is hopeless, but I'd like to 
try and make this work without unnecessary workarounds, if possible.


To demonstrate the issue, I've defined a syntax transformer that binds 
temporary names to procedures, and defines wrapper syntax transformers for 
referencing these procedures.

This syntax works fine within a module, or other non-top-level definition 
context.  But when used at the top-level, I get an unbound identifier error 
as the first procedure body is being expanded.  The first procedure 
references the second via the wrapper.


;; issue.rkt
#lang racket/base
(provide issue-syntax)
(require (for-syntax racket/base))

(define-syntax (issue-syntax stx)
  (syntax-case stx ()
    ((_ ((name param ...) body ...) ...)
     (with-syntax (((name.r ...) (generate-temporaries #'(name ...))))
       #'(begin (define-syntax (name stx)
                  (syntax-case stx ()
                    ((_ . args) #'(name.r . args))
                    (_          #'name.r))) ...
                (define name.r (lambda (param ...) body ...)) ...)))))
;; eof


> racket
Welcome to Racket v8.0 [cs].
> (require "issue.rkt")
> (let ()
    (issue-syntax
      ((foo x) (bar x 1 2))  ; note the reference to bar
      ((bar a b c) `(bar: ,a ,b ,c)))
    (foo 'is-the-top-level-hopeless?))
(bar: is-the-top-level-hopeless? 1 2)
> (issue-syntax
    ((foo x) (bar x 1 2))  ; note the reference to bar
    ((bar a b c) `(bar: ,a ,b ,c)))
; bar4: unbound identifier;
;  also, no #%top syntax transformer is bound
;   in: bar4
; [,bt for context]
> ,bt
; bar4: unbound identifier;
;  also, no #%top syntax transformer is bound
;   in: bar4
;   context...:
;    /Applications/Racket v8.0/share/pkgs/xrepl-lib/xrepl/xrepl.rkt:1493:0
;    /Applications/Racket v8.0/collects/racket/repl.rkt:11:26


I can work around this issue by altering issue-syntax to forward-define 
names before using set! to initialize them:

(define-syntax (issue-syntax stx)
  (syntax-case stx ()
    ((_ ((name param ...) body ...) ...)
     (with-syntax (((name.r ...) (generate-temporaries #'(name ...))))
       #'(begin (define-syntax (name stx)
                  (syntax-case stx ()
                    ((_ . args) #'(name.r . args))
                    (_          #'name.r))) ...
                (define name.r #f) ...  ; forward definitions
                (set! name.r (lambda (param ...) body ...)) ...)))))


Is there a better alternative?

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/cd8675e8-95d0-4552-badc-d4ec7a430109n%40googlegroups.com.

Reply via email to