I tried all four solutions and I learned a lot of new things about Racket macros I decided to go with quasisyntax because it seems more basic and easier to comprehend, and because my actual use case is simple enough.
I put here the solutions for the record.
Helper macros
(require (for-syntax syntax/parse))
(begin-for-syntax
(require racket (for-syntax syntax/parse))
(define-syntax (helper stx)
(syntax-parse stx
[(_ stuff ...)
#'#'(list stuff ...)])))
(define-syntax (main-macro stx)
(syntax-parse stx
[(_ stuff:expr ...)
(helper stuff ...)]))
(main-macro 1 2 3)
This worked nicely and is rather intuitive. Note that I used a double #'
in helper
, which yields a macro expanding to a syntax template.
Template metafunctions
(require (for-syntax syntax/parse))
(begin-for-syntax
(require syntax/parse/experimental/template)
(define-template-metafunction (helper stx)
(syntax-parse stx
[(_ stuff ...)
#'(list stuff ...)])))
(define-syntax (main-macro stx)
(syntax-parse stx
[(_ stuff:expr ...)
#'(helper stuff ...)]))
(main-macro 1 2 3)
define-template-metafunction
is really powerful! However, I couldn't easily make it work with Typed Racket, because some type annotations were missing, and I didn't investigate further.
Syntax classes
(require (for-syntax syntax/parse))
(begin-for-syntax
(define-syntax-class helper
(pattern (stuff:expr ...))))
(define-syntax (main-macro stx)
(syntax-parse stx
[(_ a:helper)
#'(list a.stuff ...)]))
(main-macro (1 2 3))
In this case, the syntax class allows capturing different parts which can then be assembled into the final template. Syntax classes are very useful, but I don't think I can make meaningful use of them in my concrete situation.
Quasisyntax and quasisyntax-splicing
(require (for-syntax syntax/parse))
(define-for-syntax (helper stx-fragment)
#`(list #,@stx-fragment))
(define-syntax (main-macro stx)
(syntax-parse stx
[(_ stuff:expr ...)
(helper #'(stuff ...))]))
(main-macro 1 2 3)
This is just a copy of @SamPhillips's answer which I put here for the record. I find that this version is very useful to somebody who is still learning about macros, because syntax transformations are explicitly visible.