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

From: J. Ian Johnson (ianj at ccs.neu.edu)
Date: Fri Aug 1 18:20:57 EDT 2014

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.
----- 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 
;; 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))) 
(define-syntax reciever 
(lambda (stx) 
(syntax-parse stx 
(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) 

;x3: unbound identifier; 
; also, no #%top syntax transformer is bound in: x3 

  Racket Users list:

Posted on the users mailing list.