The essential primitive here seems to me to be:
(define-syntax (splice stx)
(syntax-case stx ()
[(_ e ...)
(eval-syntax #'(begin e ...))]))
With with-quasisyntax being:
(define-syntax-rule
(with-quasisyntax ([a b] ...) template)
(splice (with-syntax ([a b] ...) (quasisyntax template))))
The purpose of the extension is to allow programmers to compute some parts of their program
rather than write
them, and to do so seamlessly and conveniently
In Racket we generally think instead about creating either language extensions or new sub-languages. Code generation happens to be the way we implement the extensions or sub-languages, but the focus is on the new syntax we are defining. If we find repeated patterns of code we start by thinking about the language or language feature we wish was there, and then implement that. Within those implementations we use abstractions like syntax-parse, syntax classes, and syntax-parse template metafunctions.
Without the whole picture of the problem you're trying to solve, it's hard to evaluate how splices compare to those alternatives, though.
That said, here are two alternative implementations of splice:
(define-syntax (splice2 stx)
(syntax-case stx ()
[(_ e ...)
#`(let-syntax ([m (lambda (stx) e ...)]) (m))]))
(require (for-syntax racket/syntax))
(define-syntax (splice3 stx)
(syntax-case stx ()
[(_ e ...)
(syntax-local-eval #'(begin e ...))]))
Whereas eval-syntax only allows access to the module-level expander environment, these can access the local environment. That might matter if you need to use syntax-local-value to access information from syntax bindings. The following works with splice2 and splice3, but not splice:
(let-syntax ([x 'foo])
(splice3
(displayln (syntax-local-value #'x))
#'(void)))
I recommend using splice3 because it avoids the intermediate expansion step of the let-syntax .