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 racket-users+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/5e7615aa.1c69fb81.fec6a.0fe0SMTPIN_ADDED_MISSING%40gmr-mx.google.com.