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 <michael....@gmail.com 
> <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 <michael....@gmail.com> 
>>> 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 <
>>>>> sorawe...@gmail.com> 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 racket...@googlegroups.com.
>>>> 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 racket...@googlegroups.com <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 racket-users+unsubscr...@googlegroups.com.
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