> I think there is a bug in the documentation (or maybe in Racket) because when I try `(syntax-local-eval #'(begin e ...) #f)`
Thanks for the report, I submitted a PR with a fix (https://github.com/racket/racket/pull/3964). Referring back to your original message, > (Of course, if I had more structs I would make certain things reusable, it just demonstrates the concept.) I don't understand how you would use `splice` there. It seems like you would make a macro that takes in information about the fields, etc. In the body of the macro you are already writing phase 1 code, and the output is already used as generated code. Where does `splice` come in? In case it's helpful, here's an example of how you might use a helper macro to separate out the work related to the association list representation: http://pasterack.org/pastes/11555 On Tuesday, August 17, 2021 at 8:56:52 PM UTC-4 Ryan Kramer wrote: > Thank you! `splice` is indeed the essential primitive here, so it's nice > to see it extracted and named properly. > > The difference between eval-syntax and syntax-local-eval is good to know > also. I think there is a bug in the documentation (or maybe in Racket) > because when I try `(syntax-local-eval #'(begin e ...) #f)` I get > > ..\..\Program Files\Racket-8.0.0.11\collects\racket\syntax.rkt:234:0: > syntax-local-bind-syntaxes: contract violation > expected: (or/c internal-definition-context? (listof > internal-definition-context?)) > given: #f > > No big deal, the empty list works, but the documentation says #f should be > accepted too. > > > Without the whole picture of the problem you're trying to solve, it's > hard to evaluate how splices compare to those alternatives, though. > > When choosing how to implement a macro, my first thought is "can I make > define-syntax-rule work?" And if the answer is yes, then I use it -- I > won't need the documentation and probably won't make a mistake. On the > other end of the spectrum is syntax-parse which is way more powerful, but I > will certainly need the documentation and mistakes are more likely. When I > stumbled upon my splice variant, it seemed to be only slightly more complex > than define-syntax-rule while enabling a much wider range of usage > patterns. Or so I thought at the time, but now I'm less sure. I'll have to > see how it plays out. > On Monday, August 16, 2021 at 12:22:02 PM UTC-5 Michael Ballantyne wrote: > >> 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 <[email protected]> >>> 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 >>>> [email protected]. >>>> 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 [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/7c0dc68d-60ce-4e29-bc80-d5047bbbbe12n%40googlegroups.com.

