[racket users] Macros sharing data?

45 views
Skip to first unread message

Kevin Forchione

unread,
Oct 21, 2020, 1:07:18 PM10/21/20
to Racket-Users List
Hi guys,
Suppose I have a macro that computes a value and then calls another macro in its template. Is there a way to share that data with the 2nd macro without passing it as an argument?

Thanks!
Kevin

Ben Greenman

unread,
Oct 21, 2020, 1:11:08 PM10/21/20
to Racket-Users List
You can use syntax-local-value to communicate across macros.

Here's an example:
https://docs.racket-lang.org/syntax-parse-example/index.html?q=cross-macro#(mod-path._syntax-parse-example%2Fcross-macro-communication%2Fcross-macro-communication)
> --
> 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 racket-users...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/racket-users/5425EC92-110D-47B4-BCFB-D2B6C09BBF32%40gmail.com.
>

Kevin Forchione

unread,
Oct 21, 2020, 4:16:37 PM10/21/20
to Racket-Users List


> On Oct 21, 2020, at 10:33 AM, William G Hatch <wil...@hatch.uno> wrote:
>
> On Wed, Oct 21, 2020 at 10:07:12AM -0700, Kevin Forchione wrote:
>> Hi guys,
>> Suppose I have a macro that computes a value and then calls another macro in its template. Is there a way to share that data with the 2nd macro without passing it as an argument?
>
> Take a look at syntax parameters and syntax-local-value.
>
> Syntax parameters, somewhat similar to `parameterize` for runtime
> code, allow macros to have an implicit communication channel. The
> macro that `syntax-parameterize`es sets a value for the given
> parameter which is usually accessed by simply using the syntax
> parameter in its template somewhere. The syntax parameter may even be
> passed in to the macro as an argument and thus end up in the template.
> This is how `this` gets its value in the class macro -- it's a syntax
> parameter.
>
> However, if you want an inner macro to be able to inspect the value
> given to a syntax parameter, it can use `syntax-parameter-value` to
> get the current value out and do something with it.
>
> `syntax-local-value` is another useful tool for macros to communicate.
> When you `define-syntax` an identifier, you give it a transformer
> binding. Usually the value is a procedure (a macro transformer), but
> it can actually be other data. One popular type of data to use is a
> struct that implements `prop:procedure`, and can thus act as a macro
> transformer as well as a storage place for data (which can be
> inspected by the struct's procedure interface or by other code). To
> access this data, you pass the identifier (as a syntax object) that
> you `define-syntax`ed to `syntax-local-value`.
>
> Without knowing more about what you're trying to do I'm not sure what
> more concrete advice I can give, but syntax parameters and
> `syntax-local-value` are two of the killer features that make Racket's
> macro system so powerful, so I recommend anyone who wants to use
> macros to become familiar with them.


Here’s a toy example. It generates an error, but hopefully conveys the idea I’m trying to express.

#lang racket

(require (for-syntax syntax/parse)
racket/stxparam
racket/stxparam-exptime)

(define-syntax-parameter mval 1)

(define-syntax (foo stx)
(syntax-parse stx
[(_ m:number n:number)
#'(syntax-parameterize ([mval m])
(bar n))]))

(define-syntax (bar stx)
(syntax-parse stx
[(_ n) #'(* (syntax-parameter-value mval) n)]))

(foo 3 5)

Kevin

Kevin Forchione

unread,
Oct 21, 2020, 6:44:21 PM10/21/20
to Racket-Users List

>
> Here’s a toy example. It generates an error, but hopefully conveys the idea I’m trying to express.
>
> #lang racket
>
> (require (for-syntax syntax/parse)
> racket/stxparam
> racket/stxparam-exptime)
>
> (define-syntax-parameter mval 1)
>
> (define-syntax (foo stx)
> (syntax-parse stx
> [(_ m:number n:number)
> #'(syntax-parameterize ([mval m])
> (bar n))]))
>
> (define-syntax (bar stx)
> (syntax-parse stx
> [(_ n) #'(* (syntax-parameter-value mval) n)]))
>
> (foo 3 5)

It dawned on me that since both computations take place at runtime I can simply use a parameter!

Kevin

Reply all
Reply to author
Forward
0 new messages