Subject: Re: bug#72344: [PATCH] Add a version of cl-once-only which handles lists of forms

From: Thuna <[email-masked]>
Date: Mon, 29 Jul 2024 21:54:48 +0200

> To be honest, cl-once-only* seems quite esoteric.  Could you perhaps
> show me a direct comparison between some cl-once-only code and how it is
> made more readable by cl-once-only*?  That seems to me to be the key
> criteria.

`cl-once-only*' is meant to work in situations where `cl-once-only' does
not, namely a situation where you do not know the number of forms to be
evaluated.

While such a situation *could* exist without, the cases which benefit
from `cl-once-only*' are overwhelmingly likely to be of the

  (defmacro _ (control &rest args)
    `(progn
       (do-something-with-control ,@args)
       (foo ,@args)))

variety.  The problem here is that the forms in ARGS will be evaluated
twice while we only want it to happen once.  An alternative way to
achieve this would be to do

  (defmacro _ (control &rest args)
    (cl-with-gensyms (argslist)
      `(let ((,argslist (list ,@args)))
         ...)))

and either let-bind ARGS to ARGSLIST or only refer to ARGSLIST within
the body, keeping in mind that ARGSLIST is only a symbol during
macroexpansion and that in order to refer to individual arguments you
need to do (nth N ,ARGSLIST) such that the expanded code itself finds
the relevant argument among all the ones.

With `cl-once-only*', ARGSLIST (or rather ARGS) is not a symbol but a
list of symbols so to refer to the individual argument you do ,(nth N
ARGS) and you can simply wrap your macro which worked (sans the double
evaluating) without the `cl-once-only*' and it should simply* work out of
the box.

(* There is a problem with, say, checking `macroexp-const-p' on the
given arguments, but that is not something that is too difficult to
correct, within reason, and `cl-once-only' doesn't do it either so I
don't think it matters too much.)

> Also, I wonder if a name like cl-list-once-only would be better.

I don't necessarily think that that name is bad but it doesn't quite get
to the heart of the macro either.

The macro is meant to be a `cl-once-only' which works on a list of
forms, and I feel that the "of forms" part is more important than the
"list" part, which is conceptually more likely to take on a meaning of
some ambiguous "collection" rather than a chain of cons cells.