>  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.

Reply via email to