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 <[email protected]> 
> 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 [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
> .
>

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

Reply via email to