As Alexis notes, getting the arrows right in general is tricky. But `block` 
is also currently buggy in that it does not expand to `#%expression` when 
not in an expression context. (`block` is buggy in at least one other way 
as well, but that needs a deeper fix: 
https://github.com/racket/racket/issues/3198)

On Sunday, June 7, 2020 at 4:45:34 PM UTC-6, Sorawee Porncharoenwase wrote:
>
> Wow, so block is currently buggy?!
>
> On Sun, Jun 7, 2020 at 3:31 PM Michael Ballantyne <[email protected] 
> <javascript:>> wrote:
>
>> Hah! You're right. The arrow points to the inner definition. But it's 
>> even worse than that---the value comes from the outer definition! At least 
>> for `block`, which is what I'm testing with as I haven't copied down your 
>> code. Try this:
>>
>> #lang racket
>>
>> (require racket/block)
>>
>> (define-syntax-rule (m) (displayln 'old))
>>
>> (let ()
>>   (block (m))
>>   (define-syntax-rule (m) 'new)
>>   (void))
>>
>> (and with your macro rather than block)
>>
>> On Sunday, June 7, 2020 at 4:27:24 PM UTC-6, Sorawee Porncharoenwase 
>> wrote:
>>>
>>> Perhaps I missed something, but the error in the first example is 
>>> because there’s no expression at the end of let. If I use this code 
>>> instead, it seems to work fine, with the arrow of m pointing to the 
>>> “new” one.
>>>
>>> (define-syntax-rule (m) 'old)
>>>
>>> (let ()
>>>   (list+ (m))
>>>   (define-syntax-rule (m) 'new)
>>>   (void))
>>>
>>> The second example perfectly shows why I need 
>>> internal-definition-context-track, however. Thank you very much.
>>>
>>> On Sun, Jun 7, 2020 at 7:51 AM Michael Ballantyne <[email protected]> 
>>> wrote:
>>>
>>>> >  I am unable to come up with a program where this difference is 
>>>> significant though
>>>>
>>>> Here's an example:
>>>>
>>>> (define-syntax-rule (m) 'old)
>>>>
>>>> (let ()
>>>>   ($list
>>>>    (m))
>>>>   (define-syntax-rule (m) 'new))
>>>>
>>>>
>>>> > So I am curious why internal-definition-context-track is needed.
>>>>
>>>> A similar example shows the need here:
>>>>
>>>> ($list
>>>>   (define-syntax-rule (m) 5)
>>>>   (m))
>>>>
>>>> Without `internal-definition-context-track` you'll miss the arrow for 
>>>> `m`. While `m` does indeed get rebound in the `letrec-syntaxes+values`, 
>>>> that binding has an extra scope, so the reference to `m` (recorded in an 
>>>> `'origin` property on `5`) doesn't match. 
>>>>
>>>>
>>>>
>>>> On Sunday, June 7, 2020 at 12:18:26 AM UTC-6, Sorawee Porncharoenwase 
>>>> wrote:
>>>>>
>>>>> Thank you so much, Michael! This is very helpful.
>>>>>
>>>>> I can see that when this form is used within another internal 
>>>>> definition context, then my version and your version will expand in 
>>>>> different order, and I agree that yours makes more sense. I am unable to 
>>>>> come up with a program where this difference is significant though (e.g., 
>>>>> one fails while the other doesn’t). “so that names bound by later 
>>>>> definitions are available” seems to suggest that things like this is not 
>>>>> supposed to work on my version:
>>>>>
>>>>> (let ()
>>>>>   ($list (define (f x) (g x))
>>>>>          (println f))
>>>>>   (define (g x) x)
>>>>>   (void))
>>>>>
>>>>> but it actually does…
>>>>>
>>>>> I also have another question. When should I use 
>>>>> internal-definition-context-track? Normally, internal definitions are 
>>>>> expanded into letrec-syntaxes+values, so the bindings don’t actually 
>>>>> disappear. So I am curious why internal-definition-context-track is 
>>>>> needed.
>>>>>
>>>>> Thanks again.
>>>>>
>>>>> On Sat, Jun 6, 2020 at 8:21 AM Michael Ballantyne <
>>>>> [email protected]> wrote:
>>>>>
>>>>>> Explicitly expanding `e` would ensure that the expansion work only 
>>>>>> has to happen once, rather than twice. Even so, the fully-expanded 
>>>>>> syntax 
>>>>>> will be expanded again in `syntax-local-bind-syntaxes` and in the 
>>>>>> expansion.
>>>>>>
>>>>>> As far as I've seen, the only thing that liberal define contexts 
>>>>>> control is whether definitions of functions that accept keyword 
>>>>>> arguments 
>>>>>> expand to a normal `define-values` with runtime handling of keywords, or 
>>>>>> expand to a collection of macros and function definitions that allow a 
>>>>>> more 
>>>>>> efficient calling convention for first-order calls. The latter expansion 
>>>>>> doesn't work for contexts like `class` where function definitions are 
>>>>>> re-interpreted in a way that adds indirection, so it is only enabled in 
>>>>>> contexts that opt-in.
>>>>>>
>>>>>> I see more bug in your macro: as its very first task, it should check 
>>>>>> if `(syntax-local-context)` is `'expression`. If not, it should expand 
>>>>>> to 
>>>>>> `(#%expression <the-original-call>)`. This ensures that its expansion is 
>>>>>> delayed until the second pass of the surrounding definition context so 
>>>>>> that 
>>>>>> names bound by later definitions are available. 
>>>>>>
>>>>>> On Saturday, June 6, 2020 at 4:15:00 AM UTC-6, Sorawee 
>>>>>> Porncharoenwase wrote:
>>>>>>>
>>>>>>> Ah, apparently I need syntax-local-identifier-as-binding. Here’s a 
>>>>>>> revised code that passes the tests.
>>>>>>>
>>>>>>> (begin-for-syntax
>>>>>>>   (define ((do-it gs ctx) e)
>>>>>>>     (let loop ([e e])
>>>>>>>       (define e-expanded (local-expand e
>>>>>>>                                        (list gs)
>>>>>>>                                        (list #'begin
>>>>>>>                                              #'define-syntaxes
>>>>>>>                                              #'define-values)
>>>>>>>                                        ctx))
>>>>>>>       (syntax-parse e-expanded
>>>>>>>         #:literals (begin define-syntaxes define-values)
>>>>>>>         [(begin body ...) #`(begin #,@(map loop (attribute body)))]
>>>>>>>         [(define-values (x ...) e)
>>>>>>>          #:with (x* ...) (map syntax-local-identifier-as-binding
>>>>>>>                               (attribute x))
>>>>>>>          (syntax-local-bind-syntaxes (attribute x) #f ctx)
>>>>>>>          #'(define-values (x* ...) e)]
>>>>>>>         [(define-syntaxes (x ...) e)
>>>>>>>          #:with (x* ...) (map syntax-local-identifier-as-binding
>>>>>>>                               (attribute x))
>>>>>>>          (syntax-local-bind-syntaxes (attribute x) #'e ctx)
>>>>>>>          #'(define-syntaxes (x* ...) e)]
>>>>>>>         [e #'(set! acc (cons e acc))]))))
>>>>>>>
>>>>>>> Still not sure if there’s still anything wrong. In particular, do I 
>>>>>>> need to expand e in define-syntaxes? And do I need to use 
>>>>>>> prop:liberal-define-context for gs? (I don’t understand what 
>>>>>>> liberal expansion is even after reading the docs several times) Both of 
>>>>>>> these are done in the implementation of block, but without them, it 
>>>>>>> seems to work equally well.
>>>>>>>
>>>>>>> On Fri, Jun 5, 2020 at 6:30 PM Sorawee Porncharoenwase <
>>>>>>> [email protected]> wrote:
>>>>>>>
>>>>>>>> Hi Racketeers,
>>>>>>>>
>>>>>>>> I’m creating a macro that collects values in the 
>>>>>>>> internal-definition context. E.g.,
>>>>>>>>
>>>>>>>> ($list 
>>>>>>>>  1
>>>>>>>>  (define x 2)
>>>>>>>>  x)
>>>>>>>>
>>>>>>>> should evaluate to '(1 2).
>>>>>>>>
>>>>>>>> Here’s my implementation, and it kinda works:
>>>>>>>>
>>>>>>>> #lang racket
>>>>>>>>
>>>>>>>> (begin-for-syntax
>>>>>>>>   (define ((do-it gs ctx) e)
>>>>>>>>     (let loop ([e e])
>>>>>>>>       (define e-expanded (local-expand e (list gs) #f ctx))
>>>>>>>>       (syntax-case e-expanded (begin define-syntaxes define-values)
>>>>>>>>         [(begin body ...)
>>>>>>>>          #`(begin #,@(map loop (syntax->list #'(body ...))))]
>>>>>>>>         [(define-values ids e)
>>>>>>>>          (begin
>>>>>>>>            (syntax-local-bind-syntaxes (syntax->list #'ids) #f ctx)
>>>>>>>>            e-expanded)]
>>>>>>>>         [(define-syntaxes ids e)
>>>>>>>>          (begin 
>>>>>>>>            (syntax-local-bind-syntaxes (syntax->list #'ids) #'e ctx)
>>>>>>>>            #'(begin))]
>>>>>>>>         [e #'(set! acc (cons e acc))]))))
>>>>>>>>
>>>>>>>> (define-syntax ($list stx)
>>>>>>>>   (define gs (gensym))
>>>>>>>>   (define ctx (syntax-local-make-definition-context))
>>>>>>>>   (syntax-case stx ()
>>>>>>>>     [(_ body ...)
>>>>>>>>      #`(let ([acc '()])
>>>>>>>>          #,@(map (do-it gs ctx) (syntax->list #'(body ...)))
>>>>>>>>          (reverse acc))]))
>>>>>>>>
>>>>>>>> ($list 1
>>>>>>>>        (define x 2)
>>>>>>>>        x)
>>>>>>>>
>>>>>>>> There are problems though. If I change define to define2 as 
>>>>>>>> follows:
>>>>>>>>
>>>>>>>> (define-syntax-rule (define2 x y)
>>>>>>>>   (define-values (x) y))
>>>>>>>>
>>>>>>>> ($list 1
>>>>>>>>        (define2 x 2)
>>>>>>>>        x)
>>>>>>>>
>>>>>>>> Then I get the “identifier used out of context” error. This doesn’t 
>>>>>>>> make sense to me at all. My define2 should be very similar to 
>>>>>>>> define…
>>>>>>>>
>>>>>>>> There’s also another weird problem:
>>>>>>>>
>>>>>>>> ($list 1
>>>>>>>>        (define-syntax (x stx) #'2)
>>>>>>>>        x)
>>>>>>>>
>>>>>>>> The above works perfectly, but by wrapping x with #%expression, I 
>>>>>>>> get the “identifier used out of context” error again.
>>>>>>>>
>>>>>>>> ($list 1
>>>>>>>>        (define-syntax (x stx) #'2)
>>>>>>>>        (#%expression x))
>>>>>>>>
>>>>>>>> What did I do wrong?
>>>>>>>>
>>>>>>>> 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 [email protected].
>>>>>> To view this discussion on the web visit 
>>>>>> https://groups.google.com/d/msgid/racket-users/748eead8-76b9-43bc-94da-2c832ba8896do%40googlegroups.com
>>>>>>  
>>>>>> <https://groups.google.com/d/msgid/racket-users/748eead8-76b9-43bc-94da-2c832ba8896do%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>>>> .
>>>>>>
>>>>> -- 
>>>> 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/ae981bda-94d3-43d2-ae23-a41f5160aa0ao%40googlegroups.com
>>>>  
>>>> <https://groups.google.com/d/msgid/racket-users/ae981bda-94d3-43d2-ae23-a41f5160aa0ao%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>> .
>>>>
>>> -- 
>> 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] <javascript:>.
>> To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/racket-users/30972297-14f6-4cf9-8821-de5753f3dacfo%40googlegroups.com
>>  
>> <https://groups.google.com/d/msgid/racket-users/30972297-14f6-4cf9-8821-de5753f3dacfo%40googlegroups.com?utm_medium=email&utm_source=footer>
>> .
>>
>

-- 
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/f183fa2c-8ff0-4f26-9aae-fe5acb19ba79o%40googlegroups.com.

Reply via email to