Re: [racket-users] questions about top-level-bind-scope in root-expand-context

2020-03-31 Thread Yongming Shen
I have done some further digging. Looks like it is non-trivial to remove 
the top-level-bind-scope and still preserve the current behaviors of 
top-level `define-values` and `define-syntaxes`. In particular, through 
`as-expand-time-top-level-bindings` in "expander/expand/bind-top.rkt", both 
top-level `define-values` and `define-syntaxes` use 
`select-defined-syms-and-bind!/ctx` from "expander/expand/def-id.rkt", 
which selects variable-symbols and binds them at the same time. So after a 
variable symbol is selected, a binding must be created for it. For 
top-level `define-values` and `define-syntaxes`, using the 
top-level-bind-scope for that mandatory binding is necessary to achieve the 
current top-level behaviors. On the other hand, uses of the 
top-level-bind-scope that are related to `#%top` (such as in 
"expander/expand/expr.rkt" and "expander/expand/main.rkt") appear to be 
non-essential, but may offer minor performance advantages (really not sure).

On Tuesday, March 24, 2020 at 2:15:32 AM UTC-4, Yongming Shen wrote:
>
> Hi Matthew,
>
> Thanks for the explanations. But I'm still not convinced that the 
> top-level-bind-scope is needed. This is my current understanding. The 
> purpose of the  top-level-bind-scope is to support recursion better at the 
> top level. But for the case of `(define-values (x) ...)`, if `x` is not 
> defined yet, then implicit #%top in `...` will let `...` refer to `x`. If 
> `x` is defined, then the old definition will be used by `...`. Either way, 
> the top-level-bind-scope is not needed. For the case of `(define-syntaxes 
> (x) ...)`. As you explained, a macro can naturally recursively refer to 
> itself, simply because of how macro expansion works, so the 
> top-level-bind-scope is again not needed for recursion. Is my understanding 
> correct?
>
>
> On Monday, March 23, 2020 at 10:05:12 AM UTC-4, Matthew Flatt wrote:
>>
>> At Mon, 23 Mar 2020 01:45:40 -0700 (PDT), Yongming Shen wrote: 
>> > I tried the example you gave for my first question and it resulted in 
>> an 
>> > error. 
>>
>> Oops --- you're right. I lost track of what we try to make work at the 
>> top level. 
>>
>> > 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? 
>>
>> Since the behavior goes far back, I think this is the behavior that we 
>> decided to settle for. 
>>
>> > 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? 
>>
>> The way that evaluation, binding, and expansion are interleaved means 
>> that a `define-syntaxes` macro can refer to itself in expansions. The 
>> binding of an identifier in a macro template is resolved after the 
>> macro is applied. 
>>
>> The difference with `define` is that the right-hand side is 
>> expanded/compiled before `define` binds. 
>>
>> > 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? 
>>
>> Using `disarmed-s` in the definition of `define-values` is probably 
>> a better idea, and I'll look into that more. 
>>
>> It think it turns out not to matter, normally, because `define-values` 
>> is transparent to syntax arming via `syntax-arm` with a #t second 
>> argument (which is what the expander does). But it would be better to 
>> not rely on that. 
>>
>>

-- 
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/09bf14a5-1c1c-4718-80d7-c4414bf98d52%40googlegroups.com.


Re: [racket-users] questions about top-level-bind-scope in root-expand-context

2020-03-23 Thread Yongming Shen
Hi Matthew,

Thanks for the explanations. But I'm still not convinced that the 
top-level-bind-scope is needed. This is my current understanding. The 
purpose of the  top-level-bind-scope is to support recursion better at the 
top level. But for the case of `(define-values (x) ...)`, if `x` is not 
defined yet, then implicit #%top in `...` will let `...` refer to `x`. If 
`x` is defined, then the old definition will be used by `...`. Either way, 
the top-level-bind-scope is not needed. For the case of `(define-syntaxes 
(x) ...)`. As you explained, a macro can naturally recursively refer to 
itself, simply because of how macro expansion works, so the 
top-level-bind-scope is again not needed for recursion. Is my understanding 
correct?


On Monday, March 23, 2020 at 10:05:12 AM UTC-4, Matthew Flatt wrote:
>
> At Mon, 23 Mar 2020 01:45:40 -0700 (PDT), Yongming Shen wrote: 
> > I tried the example you gave for my first question and it resulted in an 
> > error. 
>
> Oops --- you're right. I lost track of what we try to make work at the 
> top level. 
>
> > 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? 
>
> Since the behavior goes far back, I think this is the behavior that we 
> decided to settle for. 
>
> > 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? 
>
> The way that evaluation, binding, and expansion are interleaved means 
> that a `define-syntaxes` macro can refer to itself in expansions. The 
> binding of an identifier in a macro template is resolved after the 
> macro is applied. 
>
> The difference with `define` is that the right-hand side is 
> expanded/compiled before `define` binds. 
>
> > 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? 
>
> Using `disarmed-s` in the definition of `define-values` is probably 
> a better idea, and I'll look into that more. 
>
> It think it turns out not to matter, normally, because `define-values` 
> is transparent to syntax arming via `syntax-arm` with a #t second 
> argument (which is what the expander does). But it would be better to 
> not rely on that. 
>
>

-- 
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/97759d2c-4d94-422e-b984-5ec9001b0fca%40googlegroups.com.


Re: [racket-users] questions about top-level-bind-scope in root-expand-context

2020-03-23 Thread Alexis King
> On Mar 23, 2020, at 13:46, George Neuner  wrote:
> 
> I've run into this problem before ... I don't recall the official
> explanation, but my takeaway was that Racket does not permit you to
> directly *export* a value - you have to export a function or macro
> that produces the value.
> 
> E.g., 
>  #lang racket
>  (provide fib)
>  (define (fib) "fib")

I’m not sure what issue you may have run into in the past, but Racket certainly 
has no issue with exporting a value. (After all, functions are values.) The 
issue described in this thread is (a) entirely syntactic (it’s an issue of 
binding/scoping, not runtime behavior), and (b) only occurs at the top-level 
(i.e. in the REPL, outside of a module). Matthew has already provided a 
detailed explanation of why the issue occurs.

It’s true that you cannot set! imported bindings, but that’s quite separate 
from the problem discussed in this thread (which appears to be resolved).

-- 
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/DB94641E-A018-4A1D-BEE3-47DD183D7B54%40gmail.com.


Re: [racket-users] questions about top-level-bind-scope in root-expand-context

2020-03-23 Thread Matthew Flatt
At Mon, 23 Mar 2020 01:45:40 -0700 (PDT), Yongming Shen wrote:
> I tried the example you gave for my first question and it resulted in an 
> error.

Oops --- you're right. I lost track of what we try to make work at the
top level.

> 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?

Since the behavior goes far back, I think this is the behavior that we
decided to settle for.

> 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?

The way that evaluation, binding, and expansion are interleaved means
that a `define-syntaxes` macro can refer to itself in expansions. The
binding of an identifier in a macro template is resolved after the
macro is applied.

The difference with `define` is that the right-hand side is
expanded/compiled before `define` binds.

> 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?

Using `disarmed-s` in the definition of `define-values` is probably
a better idea, and I'll look into that more.

It think it turns out not to matter, normally, because `define-values`
is transparent to syntax arming via `syntax-arm` with a #t second
argument (which is what the expander does). But it would be better to
not rely on that.

-- 
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/5e78c215.1c69fb81.5b855.0569SMTPIN_ADDED_MISSING%40gmr-mx.google.com.


Re: [racket-users] questions about top-level-bind-scope in root-expand-context

2020-03-23 Thread Yongming Shen
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 racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/a6f90504-7260-41ea-b8d7-

Re: [racket-users] questions about top-level-bind-scope in root-expand-context

2020-03-21 Thread Matthew Flatt
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.


[racket-users] questions about top-level-bind-scope in root-expand-context

2020-03-21 Thread Yongming Shen
Hi,

I noticed that top level (define-values ...) forms create bindings that 
include the top-level-bind-scope (of the namespace's root-expand-context), 
and have two questions related to this.

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?

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?

Thanks!

-- 
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/3a1ee8c8-a990-4337-840a-5458d2ee36c7%40googlegroups.com.