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] 
> <javascript:>> 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] <javascript:>.
>> 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.

Reply via email to