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 racket-users+unsubscr...@googlegroups.com.
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