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

Reply via email to