Subject: bug#76132: Clojure-style auto-gensyms for macros

From: Thierry Volpiatto <[email-masked]>
Date: Sat, 08 Feb 2025 03:27:57 +0000

Tassilo Horn <[email-masked]> writes:

> Tags: patch
>
> Hi all,
>
> in a recent bug report the topic macro hygiene came up, i.e., that a
> macro which introduces local bindings in its expansion better uses
> uninterned symbols for those in order not to clash with code passed as
> macro arguments which are spliced into the expansion.
>
> Clojure has a very convenient feature to make that easy.  While you can
> write such macros traditionally like
>
> (defmacro foo [x y]
>   (let [xv (gensym "x")
>         yv (gensym "y")]
>     `(let [,xv ,x
>            ,yv ,y]
>        (do-stuff (* ,xv ,xv) (* ,yv ,yv)))))
>
> you can also write much more concise and convenient
>
> (defmacro foo [x y]
>   `(let [xv# ,x
>          yv# ,y]
>      (do-stuff (* xv# xv#) (* yv# yv#))))

Don't we have cl-with-gensyms which is very convenient as well?
In Helm we have helm-with-gensyms which is the same (Thanks Michael ;-))

> where each symbol ending in # will be replaced by a unique gensymed
> symbol (per name).  The expansion of the two macros is the same.
>
> Would there be interest in adding something like that to Elisp?
>
> I've attached a proof-of-concept implementation where the feature is
> provided by a macro with-uninterned-symbols [1] which you simply wrap
> around your backquoted form.
>
> [1] In Clojure, it's a feature of the reader triggered by backquote.
>
> In GNU Emacs 31.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version
>  3.24.48, cairo version 1.18.2) of 2025-02-07 built on thinkpad-t440p
> Repository revision: 1751739152149608d28853782ce53b0b9a749bb2
> Repository branch: master
> System Description: Arch Linux
>
> Configured using:
>  'configure --without-native-compilation --with-modules --with-pgtk'
>
>

-- 
Thierry