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/CADcuegv8EPsUjHmLq9uDDXRK2u0p%3D7zdU3XcMdqtA_9jr_%2BXzw%40mail.gmail.com.

Reply via email to