[racket] getting one macro to tell another macro to define something

From: Alexander D. Knauth (alexander at knauth.org)
Date: Fri Aug 8 19:45:32 EDT 2014

Ok I tried it, it worked, and I made a pull request.  
https://github.com/plt/racket/pull/749

On Aug 8, 2014, at 6:33 PM, Alexander D. Knauth <alexander at knauth.org> wrote:

> 
> On Aug 1, 2014, at 6:45 PM, J. Ian Johnson <ianj at ccs.neu.edu> wrote:
> 
>> Well one problem is expander application his its own mark to deal with, so you can't cancel the mark on x.
>> 
>> https://github.com/plt/racket/blob/master/racket/collects/racket/match/parse-helper.rkt#L157
>> 
>> Another problem is expecting the implementation of match-define to not have any inner macros that would change syntax-local-introduce to a less helpful extent.
>> What would be ideal is if racket/match could change some "parameter" so that syntax-local-introduce used the introducer defined in the above link,
> 
> Well what if match-expander-transform did something like this:
> From racket/require-syntax.rkt:
> (define-for-syntax current-require-introducer
>  (make-parameter (lambda (x) (error "not expanding require form"))))
> 
> (define-for-syntax (syntax-local-require-introduce x)
>  (unless (syntax? x)
>    (raise-argument-error 'syntax-local-introduce-require "syntax?" x))
>  ((current-require-introducer) x))
> 
>> since the generated temporary does not have x's mark that x has annihilated. Instead x's mark will be added to tmp after the transformer returns, and there's nothing you can do about it :(
>> 
>> -Ian
>> ----- Original Message -----
>> From: "Alexander D. Knauth" <alexander at knauth.org>
>> To: "J. Ian Johnson" <ianj at ccs.neu.edu>
>> Cc: "racket users list" <users at racket-lang.org>
>> Sent: Friday, August 1, 2014 6:31:59 PM GMT -05:00 US/Canada Eastern
>> Subject: Re: [racket] getting one macro to tell another macro to define something
>> 
>> Well, if the match-expander is invoked in the “dynamic extent” of the match-define form, then would syntax-local-introduce apply that syntax-mark?  
>> 
>> On Aug 1, 2014, at 6:20 PM, J. Ian Johnson <ianj at ccs.neu.edu> wrote:
>> 
>>> Well that's a pickle. I can tell you that (mac . args) gets expanded as (X[mac^m] . X[args^m])^m where m is a fresh mark and X expands a form. If m is applied to something with m already, they annihilate each other (see Syntactic Abstraction in Scheme for how this totally works).
>>> The syntax-local-introduce form allows you to apply the macro application's mark to an arbitrary piece of syntax, so later on the application's mark will annihilate it and voila`, it's like it was textually given to the macro application itself.
>>> 
>>> Here, however, a match expander is not treated as a macro invocation. There is no mark for that match-expander use to introduce. There is, however, the mark from match-define that you'll want to introduce to this temporary you've generated. I think. I haven't quite worked out how to make this work.
>>> -Ian
>>> ----- Original Message -----
>>> From: "Alexander D. Knauth" <alexander at knauth.org>
>>> To: "racket users list" <users at racket-lang.org>
>>> Sent: Friday, August 1, 2014 5:55:57 PM GMT -05:00 US/Canada Eastern
>>> Subject: Re: [racket] getting one macro to tell another macro to define something
>>> 
>>> 
>>> 
>>> 
>>> 
>>> On Aug 1, 2014, at 5:37 PM, J. Ian Johnson < ianj at ccs.neu.edu > wrote: 
>>> 
>>> 
>>> It's best to expand into a begin-for-syntax that does the desired mutation, rather than mutate within the transformer. You currently _cannot_ do this outside top level forms. 
>>> 
>>> 
>>> 
>>> The reason I can’t do that is because in the real program, sender is actually a match-expander. 
>>> 
>>> 
>>> You are also right about the marks. The call to receiver adds additional marks to the definitions that it pulls out, so you'll need to apply syntax-local-introduce. ... 
>>> 
>>> 
>>> 
>>> 
>>> On Aug 1, 2014, at 5:39 PM, Ryan Culpepper < ryanc at ccs.neu.edu > wrote: 
>>> 
>>> 
>>> Use syntax-local-introduce when putting syntax into a side-channel or getting it back out across macro calls. This only matters when the syntax represents a definition or more generally contains binders whose references are not all in the same syntax. 
>>> ... 
>>> 
>>> 
>>> Thanks, the syntax-local-introduce got it working for that example, but for some reason it’s not working when sender is a match-expander. 
>>> 
>>> I’m still not very clear on when to use syntax-local-introduce and when not to, or even what it does (other than get that example working), so could someone point me in the right direction? 
>>> 
>>> 
>>> 
>>> #lang racket 
>>> (require racket/stxparam 
>>> (for-syntax syntax/parse 
>>> racket/syntax 
>>> racket/set)) 
>>> ;; current-defs : (syntax-parameter-of (or/c set-mutable? #f)) 
>>> (define-syntax-parameter current-defs #f) 
>>> (define-match-expander sender 
>>> (lambda (stx) 
>>> (syntax-parse stx 
>>> [(sender x) 
>>> #:with tmp (generate-temporary #'x) 
>>> (define defs (syntax-parameter-value #'current-defs)) 
>>> (set-add! defs (syntax-local-introduce #'(define x tmp))) 
>>> #'tmp]))) 
>>> (define-syntax reciever 
>>> (lambda (stx) 
>>> (syntax-parse stx 
>>> [(reciever) 
>>> (define defs (syntax-parameter-value #'current-defs)) 
>>> (with-syntax ([(def ...) (map syntax-local-introduce (set->list defs))]) 
>>> #'(begin def ...))]))) 
>>> 
>>> 
>>> (syntax-parameterize ([current-defs (mutable-set)]) 
>>> (match-define (sender x) 1) 
>>> (reciever) 
>>> x) 
>>> 
>>> 
>>> ;x3: unbound identifier; 
>>> ; also, no #%top syntax transformer is bound in: x3 
>>> 
>>> 
>>> 
>>> 
>>> ____________________
>>> Racket Users list:
>>> http://lists.racket-lang.org/users
>> 
> 
> 
> ____________________
>  Racket Users list:
>  http://lists.racket-lang.org/users



Posted on the users mailing list.