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.

Reply via email to