Fork me on GitHub
#clojure-dev
<
2023-11-28
>
Noah Bogart14:11:19

i recently ran into a scenario when writing some complex macro-generating macros (i know lol) where it would have been helpful to not have syntax quote expansion happen at read time (i was walking a given form and gathering specific symbols). I know that in ancient times (2010), Rich removed the SYNTAX_QUOTE special form from LispReader in favor of the way it works now. Looking at the code, I think a macro in clojure.core that calls clojure.lang.LispReader$SyntaxQuoteReader/syntaxQuote would be enough to accomplish this. Would y'all be interested in such a macro? Otherwise, we have to reimplement that functionality ourselves (like Brandon Bloom's https://github.com/brandonbloom/backtick library).

Noah Bogart14:11:31

i suspect that would work but would be a breaking change, so best not to mess with it too much lol

bronsa14:11:55

syntax-quote as a macro won't happen, that'd be a breaking change indeed

bronsa14:11:20

having it available in clojure.core would be nice I guess

👍 3
bronsa14:11:37

but as you say, there are already libraries that provide it. backtick is one, tools.reader also exposes syntax-quote

Noah Bogart14:11:47

if the method was public, it would look like:

(defmacro syntax-quote [form]
  (clojure.lang.LispReader$SyntaxQuoteReader/syntaxQuote form))

bronsa14:11:33

not quite -- you also need to bind GENSYM_ENV appropriately

Noah Bogart14:11:56

ah good point

Noah Bogart14:11:37

yeah, libraries are perfectly fine, it's just nice to have features that exist within Clojure already be exposed and available for use

Noah Bogart14:11:55

(defmacro syntax-quote [form]
  (with-bindings {clojure.lang.LispReader/GENSYM_ENV {}}
    (clojure.lang.LispReader$SyntaxQuoteReader/syntaxQuote form)))
lol there we go, with some surgery in lispreader to expose GENSYM_ENV and syntaxQuote

bronsa14:11:15

yeah that'd be it :)

borkdude14:11:33

@UEENNMX0T You can expose that with some evil Java reflection ;)

😅 1
Noah Bogart14:11:40

alex, let's get this into 1.12 😎

borkdude14:11:37

btw edamame also allows getting the data structure of syntax-quote back

Noah Bogart14:11:43

lol yeah, i read that earlier. just feels like so much effort! that's 1k lines to achieve the same effect as just using the built-in java stuff

borkdude14:11:16

user=> (e/parse-string "`(do ~x)" {:syntax-quote true})
(clojure.core/sequence (clojure.core/seq (clojure.core/concat (clojure.core/list (quote do)) (clojure.core/list x))))

👍 1
Noah Bogart14:11:58

edamame reads strings, i'm working with clojure data already. i want the effect of syntax-quote, just want to defer evaluating it until the surrounding macro has been evaluated, you know?

borkdude14:11:09

yeah that's true

Noah Bogart14:11:34

i've put edamame's :syntax-quote to good use in splint, very happy for it there

borkdude14:11:39

If you're working with data, you can also prepend a quote:

user=> '`(do ~x)
(clojure.core/seq (clojure.core/concat (clojure.core/list (quote do)) (clojure.core/list x)))
I'm not sure if that's useful in your scenario

Noah Bogart14:11:39

that's actually the issue i'm trying to avoid. i have a call to a macro but i'm passing in a syntax-quoted form: (defmacro-g! ... (let ...))` , and then i'm using postwalk on the body. the postwalk sees (clojure.core/seq (clojure.core/concat (clojure.core/list (quote let)) ...)) instead of (let [...] ...) which makes determining certain things hard (is this a vector? how many entries does this map have? etc)

Noah Bogart14:11:37

with a proper syntax-quote macro, i could say (defmacro-g! ... (syntax-quote (let [...] ...))) and then postwalk would see (syntax-quote (let [...] ...))

Noah Bogart14:11:25

and then the call to defmacro-g! returns the form (syntax-quote (let ...)) and then the reader evaluates syntax-quote which would then return (clojure.core/seq (clojure.core/concat ...)) which would do what we want

Noah Bogart15:11:29

as we've seen, it's technically a solved problem in the community (officially with tools.reader and communal with backtick), i just think it's a worthwhile addition to clojure.core

1
Noah Bogart16:11:25

not to harp on this too much, just want to point out ways that changes to clojure internals can affect these libraries because they're trying to re-implement existing behavior (https://github.com/brandonbloom/backtick/issues/5) which would be solved by having a built-in syntax-quote

Noah Bogart02:11:19

here's my attempt at a syntax-quote macro wrapping the built-in SyntaxQuoteReader functionality: https://github.com/NoahTheDuke/clojure/pull/6 i've signed the CLA so looking at this should be kosher