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))))
Forms like splice appear in the metaprogramming systems of other
programming languages such as Template Haskell
(https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/exts/template_haskell.html)
and Converge (https://convergepl.org/) but I haven't seen the pattern
widely used in Racket.
I think this comes from a different philosophy. Systems like Template
Haskell think of metaprogramming as a way to automatically generate code.
>From "Template Meta-programming for Haskell"
(https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/meta-haskell.pdf):
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 .
On Friday, August 13, 2021 at 9:19:51 PM UTC-4 Ryan Kramer wrote:
> The name `with-quasisyntax` is not very good, because it is not simply a
> quasi version of `with-syntax`. The most interesting part is that it calls
> `eval-syntax` up front. The result feels like a "universal macro" -- it can
> be used to implement both foo->assoc and assoc->foo which look like they
> would traditionally need separate macros (or one large macro that handles
> both).
>
> I am noticing that this use of `eval-syntax` can cause error messages to
> be less good, but I still think it's OK for "private" code.
>
> On Fri, Aug 13, 2021 at 2:45 PM D. Ben Knoble <ben.k...@gmail.com> wrote:
>
>> Ah, I'm now seeing that with-quasi implicitly #`s the body; I believe
>> with syntax-parse, #:with, and #' + template vars + #` when needed you
>> might be ok.
>>
>> --
>> You received this message because you are subscribed to a topic in the
>> Google Groups "Racket Users" group.
>> To unsubscribe from this topic, visit
>> https://groups.google.com/d/topic/racket-users/61cQImHJfZI/unsubscribe.
>> To unsubscribe from this group and all its topics, send an email to
>> racket-users...@googlegroups.com.
>> To view this discussion on the web visit
>> https://groups.google.com/d/msgid/racket-users/2ede4034-80ec-49ad-9782-8883f8d47085n%40googlegroups.com
>>
>> <https://groups.google.com/d/msgid/racket-users/2ede4034-80ec-49ad-9782-8883f8d47085n%40googlegroups.com?utm_medium=email&utm_source=footer>
>> .
>>
>
--
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+unsubscr...@googlegroups.com.
To view this discussion on the web visit
https://groups.google.com/d/msgid/racket-users/9b9cd3f1-f046-414c-a701-04e97175a53an%40googlegroups.com.