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

From: J. Ian Johnson (ianj at ccs.neu.edu)
Date: Fri Aug 1 17:37:49 EDT 2014

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.

In this case, sender would be 
(define-syntax (sender stx)
  (syntax-case stx ()
    [(_ def) #'(begin-for-syntax (set-add! (syntax-parameter-value #'current-defs) #'def))]))

You would need your test to instead use splicing-syntax-parameterize to get the use of sender at the top level.
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.

All together this is

#lang racket
(require racket/stxparam
         racket/splicing
         (for-syntax syntax/parse
                     racket/set))
;; current-defs : (syntax-parameter-of (or/c set-mutable? #f))
(define-syntax-parameter current-defs #f)
(define-syntax (sender stx)
  (syntax-case stx ()
    [(_ def) #`(begin-for-syntax (set-add! (syntax-parameter-value #'current-defs) #'def))]))

(define-syntax reciever
  (lambda (stx)
    (syntax-parse stx
      [(reciever)
       (define defs (syntax-parameter-value #'current-defs))
       (with-syntax ([(def ...) (set-map defs syntax-local-introduce)])
         #'(begin def ...))])))

(splicing-syntax-parameterize ([current-defs (mutable-set)])
  (sender (define x 1))
  (reciever)
  x)

-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:12:00 PM GMT -05:00 US/Canada Eastern
Subject: [racket] getting one macro to tell another macro to define something

Is there any way to do something like this and have it work?:
#lang racket
(require racket/stxparam
         (for-syntax syntax/parse
                     racket/set))
;; current-defs : (syntax-parameter-of (or/c set-mutable? #f))
(define-syntax-parameter current-defs #f)
(define-syntax sender
  (lambda (stx)
    (syntax-parse stx
      [(sender def)
       (define defs (syntax-parameter-value #'current-defs))
       (set-add! defs #'def)
       #'(void)])))
(define-syntax reciever
  (lambda (stx)
    (syntax-parse stx
      [(reciever)
       (define defs (syntax-parameter-value #'current-defs))
       (with-syntax ([(def ...) (set->list defs)])
         #'(begin def ...))])))

(syntax-parameterize ([current-defs (mutable-set)])
  (sender (define x 1))
  (reciever)
  x)

Right now, x is undefined.  

I’m guessing that that’s because it has the wrong syntax marks, but is there any way around that?  
(Other that doing (datum->syntax stx (syntax->datum …)) on everything?)



____________________
  Racket Users list:
  http://lists.racket-lang.org/users


Posted on the users mailing list.