Thanks Sam.

I ended up finding another alternative, which is to replace the 
set!-followed-by-define with define-values:

(define-values (name.r ...) (values (lambda (param ...) body ...) ...))


One more related question (though given the hopelessness, I'd understand if 
there isn't a great answer):

Before writing this multi-definition syntax, I originally wrote a 
single-item version that expanded to a single pair of syntax wrapper and 
value definition:

(define-syntax (issue-syntax-single stx)
  (syntax-case stx ()
    ((_ (name param ...) body ...)
       #'(begin (define-syntax (name stx)
                  (syntax-case stx ()
                    ((_ . args) #'(name.r . args))
                    (_          #'name.r)))
                (define name.r (lambda (param ...) body ...))))))

In fact, I didn't expect to need a multi-definition version.  The hope was 
that I could define these one-by-one, even when they are 
mutually-recursive.  This does work in a module, but fails at the 
top-level.  I also tried the forward-declaration you suggest, but get the 
same error.

> (define-syntaxes (foo bar) (values))  ; attempted forward-declaration 
(did I do this correctly?)
> (issue-syntax-single (foo x) (bar x 1 2))
> (issue-syntax-single (bar a b c) `(bar: ,a ,b ,c))
> (foo 'the-top-level-is-hopeless)
; bar: undefined;
;  cannot reference an identifier before its definition
;   in module: top-level
; [,bt for context]
> ,bt
; bar: undefined;
;  cannot reference an identifier before its definition
;   in module: top-level
;   context...:
;    body of top-level
;    readline-input:8:33: name.r
;    /Applications/Racket v8.0/share/pkgs/xrepl-lib/xrepl/xrepl.rkt:1493:0
;    /Applications/Racket v8.0/collects/racket/repl.rkt:11:26

Is there another workaround that would help the single-item version?

On Monday, June 28, 2021 at 9:51:32 AM UTC-4 Sam Tobin-Hochstadt wrote:

> This is indeed an issue where "the top-level is hopeless" is the problem 
> [1].
>
> However, there's a better work-around. You can write `(define-syntaxes
> (name.r ...) (values))` to forward-declare all those names, and then
> the subsequent definitions will work correctly.
>
> Sam
>
> [1] https://lists.racket-lang.org/users/archive/2005-November/010350.html
> is a good short description of the problem here.
>
> On Fri, Jun 25, 2021 at 5:34 PM Greg Rosenblatt <greg....@gmail.com> 
> wrote:
> >
> > 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...@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
> .
>

-- 
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/f6515c74-86d0-48cd-a242-d56f719cd1f8n%40googlegroups.com.

Reply via email to