Re: [racket-users] Top-level unbound identifiers during expansion

2021-06-28 Thread Greg Rosenblatt
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  
> 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?
> >
> > 

Re: [racket-users] Top-level unbound identifiers during expansion

2021-06-28 Thread Sam Tobin-Hochstadt
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  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+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.

-- 
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/CAK%3DHD%2BYeXuQP4yErTQe3g7aCSM7iOLfkJpFXDHodZQ29zf_agg%40mail.gmail.com.


[racket-users] Top-level unbound identifiers during expansion

2021-06-25 Thread Greg Rosenblatt
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.