Wow, so block is currently buggy?!

On Sun, Jun 7, 2020 at 3:31 PM Michael Ballantyne <
[email protected]> 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].
> 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/CADcuegvqrnU9nviOUk3zmy_U1ySNsh0Tni5R%3DYKczodgFArwHw%40mail.gmail.com.

Reply via email to