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)
         (+ (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.


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 view this discussion on the web visit

Reply via email to