Hi Matthew,

Thank you for the quick reply!

I tried the example you gave for my first question and it resulted in an 
error.
I have the following as `module-that-defines-fib`:

  #lang racket
  (provide fib)
  (define fib "fib")

And this is the error that I got (using Racket 7.6):

  ; application: not a procedure;
  ;  expected a procedure that can be applied to arguments
  ;   given: "fib"
  ; [,bt for context]

I think this is because `(define-values (x) ...)` expands `...` without the 
top-level-bind-scope, even when expand-context-to-parsed? is #t (according 
to expander/expand/top.rkt). Is this a bug?
Related to your answer to my second question, `define-syntaxes` similarly 
does not add the top-level-bind-scope when expanding `...`. Does this mean 
that even for `define-syntaxes`, `...` won't use the top-level-bind-scope 
binding(s) after all?

A little bit off-topic, in the definition of define-values (in 
expander/expand/top.rkt), there is `(define-match m s ...)`, but for 
define-syntaxes it is `(define-match m disarmed-s ...)`. Is this difference 
significant? Or does define-match not care whether `s` or `disarmed-s` is 
used?

Thanks,
Yongming


On Saturday, March 21, 2020 at 9:25:01 AM UTC-4, Matthew Flatt wrote:
>
> At Sat, 21 Mar 2020 00:00:07 -0700 (PDT), Yongming Shen wrote: 
> > First, in the source file expander/expand/bind-top.rkt, there is a 
> comment 
> > that says "When compiling `(define-values (x) ...)` at the top level, 
> > we'd like to bind `x` so that a reference in the "..." will point back 
> to 
> > the definition, as opposed to being whatever `x` was before." Isn't this 
> > the exact opposite of what (define-values (x) ...) should do? 
>
> Here's an example scenario that the current rule is meant to cover: 
>
>  > (require module-that-defines-fib) 
>
>  > fib ; refers to binding from `module-that-defines-fib` 
>
>  > (define (fib n) 
>      (if (< n 2) 
>          1 
>          (+ (fib (- n 1)) (fib (- n 2))))) ; refers to this definition 
>
>  > (fib 27) ; => 514229 
>
> If a programmer usually expects the `fib`s in the definition's `...` 
> region here to refer to the new definition, not to the imported 
> binding, then the implemented rule is the right one. If programmers 
> expect that `fib`s in the `...` to refer to the imported binding, then 
> I'd agree with you. But I think the former is more often the case. 
>
> Neither rule is obviously right, and if we make the example more 
> complicated with more macros involved, I'm pretty sure there's no way 
> to implement either rule consistently: the top level is hopeless. The 
> case of a single recursive function seems common enough that we've 
> picked a rule and implementation to make it work. 
>
> > Second, ignoring the comment mentioned above, but still consider 
> > `(define-values (x) ...)`. It appears that the binding of `x` to `...` 
> with 
> > the top-level-bind-scope is only used by `(#%top . x)` (either explicit 
> or 
> > implicit). The only exception seems to be in contexts where neither `x` 
> nor 
> > #%top are binded, in which case `x`, not wrapped by #%top, also uses 
> that 
> > binding. The case of `(#%top . x)` is confusing because even without the 
> > top-level-bind-scope binding of `x`, `(#%top . x)` can still locate 
> > `(define-values (x) ...)`, otherwise mutually recursive functions won't 
> > work at the top level. As for the exception case, it seems rare enough 
> that 
> > it can be ignored. So my question is, what's benefit does the 
> > top-level-bind-scope bring? 
>
> Just to restate (to make sure I understand), you're pointing out that 
> an unbound identifier is treated the same as a binding using the 
> top-level scope (i.e., both refer to a top-level variable) --- so why 
> bother with the top-level scope? 
>
> Although the result is the same for variable references, it's not the 
> same for macro bindings or for imported bindings. And, then, there's no 
> way to predict in advance that an identifier will be used as a variable 
> and omit the top-level scope in that case. 
>
> Stepping back a little, it may not be the right design choice to treat 
> an unbound identifier as a reference to a top-level variable. But some 
> sort of default is necessary to support the traditional top level. And 
> treating unbound identifiers this was avoids a[nother] special 
> treatment of top-level scopes, where an unbound variable could be 
> treated as a variable reference only if it has a top-level scope. 
>
> Really, the only consistent approach that I know is to not have an 
> interactive top level, but that's not an attractive option. 
>
>
> Matthew 
>
>

-- 
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/a6f90504-7260-41ea-b8d7-0311c7ef7a9f%40googlegroups.com.

Reply via email to