unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Thuna <thuna.cing@gmail.com>
To: Sean Whitton <spwhitton@spwhitton.name>
Cc: 72344@debbugs.gnu.org, drew.adams@oracle.com
Subject: bug#72344: [PATCH] Add a version of cl-once-only which handles lists of forms
Date: Tue, 13 Aug 2024 23:17:41 +0200	[thread overview]
Message-ID: <874j7o2kcq.fsf@gmail.com> (raw)
In-Reply-To: <87r0b1su7p.fsf@melete.silentflame.com>

[-- Attachment #1: Type: text/plain, Size: 1136 bytes --]

>> If `cl-once-only-multiple' is fine by you then I would prefer that over
>> `cl-once-only-rest' and `cl-once-only-mult'.  It would help to get more
>> suggestions, but I don't think anyone else will be chiming in at this
>> point.
>
> It's just really long :)

I do agree that it's decently long, but it's probably fine...?
`cl-destructuring-bind' is the same length and I don't find that too
annoying to write out, though maybe that's just me.

> Let's give ourselves time to think of something shorter.

I don't have any new ideas for the name, but here's a second draft which
tries to adapt the example used in `cl-once-only'.  I was unable to get
the `mapcar' in the first example any more concise, so some thoughts on
rewording and fixing various parts of the text would be nice.

If Drew wants to start a new conversation to move `cl-once-only' (and
also this) out of cl-lib we can also just go with any name now and then
finalize it afterwards, though of all the names the one I favor is still
`cl-once-only-multiple' above all others (sans `cl-once-only*' which is
not an option - unless if you changed your mind about it?).


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: cl-texi-second-draft.patch --]
[-- Type: text/x-patch, Size: 3983 bytes --]

diff --git a/doc/misc/cl.texi b/doc/misc/cl.texi
index 57e2f3a6c3b..de9f0565d03 100644
--- a/doc/misc/cl.texi
+++ b/doc/misc/cl.texi
@@ -2684,10 +2684,10 @@ Macro-Writing Macros
 @end defmac
 
 @defmac cl-once-only* (variable forms) body
-This macro is a version of @code{cl-once-only} which takes a list of
-forms.  This macro is primarily meant to be used where the number of
-forms is unknown and thus @code{cl-once-only} cannot work, such as those
-obtained by a @code{&body} argument.
+This macro is a version of @code{cl-once-only} which takes an
+arbitrarily long list of forms.  This macro is primarily meant to be
+used where the number of forms is unknown and thus @code{cl-once-only}
+cannot work, such as those obtained by a @code{&body} argument.
 
 Each element of @var{variable} may be used to refer to the result of
 evaluating the corresponding form in @var{forms} within @var{body}.
@@ -2696,38 +2696,58 @@ Macro-Writing Macros
 such that each form is evaluated in order and its result is bound to the
 corresponding symbol.
 
-Like @code{cl-once-only}, the first argument can be a symbol
-@var{variable}, which is equivalent to writing @code{(variable
-variable)}.
+Like @code{cl-once-only}, the first argument can be a symbol @var{variable}, which
+is equivalent to writing @code{(variable variable)}.
 
 Consider the following macro:
 
 @example
-(defmacro my-list (head &rest args)
-  (cl-once-only ((args `(list ,@@args))
-    `(list (apply #',head ,args)
-           ,args
-           (nth 1 ,args))))
+(defmacro my-list (vals &rest forms)
+  (let ((val-results (mapcar (lambda (_) (gensym)) vals)))
+    `(let* ,(cl-mapcar #'list val-results vals)
+       (list ,(cl-first val-results)
+             ,(cl-second val-results)
+             ,@@val-results
+             (progn ,@@forms)))))
 @end example
 
-This macro is such that it will evaluate @var{args} only once, however
-that @var{args} was a list is lost once we are in @code{cl-once-only}.
-Furthermore, to access any specific element of @var{args} we must obtain
-the element during evaluation via @code{(nth N ,args)}.
+In a call like @code{(my-list ((pop foo) (cl-incf bar) ...) ...)} the
+@code{pop} and @code{cl-incf} will be evaluated exactly once, ensuring
+their side effects are not applied twice.  This code is however very
+complex, in the same way code not using @code{cl-once-only} is.
 
-Consider the alternative using @code{cl-once-only*}:
+Using @code{cl-once-only} is not possible directly due to it expecting
+individual forms which can be evaluated.  This can be worked around by
+assigning to a variable @code{`(list ,@@vars)} which @emph{can} be
+evaluated:
 
 @example
-(defmacro my-list (head &rest args)
-  (cl-once-only* args
-    `(list (,head ,@@args)
-           (list ,@@args)
-           ,(nth 1 args))))
+(defmacro my-list (vals &rest forms)
+  (cl-once-only ((vals `(list ,@@vals)))
+    `(list (cl-first ,vals)
+           (cl-second ,vals)
+           ,vals                        ; Does not splice
+           (progn ,@@forms))))
+@end example
+
+There are two problems which both result from the fact that @code{vals}
+is not a list inside the body of @code{cl-once-only}: 1. @code{vals}
+cannot be spliced in the way it can in the previous example and
+2. accessing individual elements of @code{vals} can only be done by
+accessing the resulting list @emph{during evaluation}.  Compare this to
+the example using @code{cl-once-only*}:
+
+@example
+(defmacro my-list (vals &rest forms)
+  (cl-once-only* vals
+    `(list ,(cl-first vals)
+           ,(cl-second vals)
+           ,@@vals
+           (progn ,@@forms))))
 @end example
 
-which preserves the fact that @var{args} is a list and allows immediate
-access to individual arguments by simply choosing the corresponding
-element in @var{args}.
+which preserves the fact the @var{vals} is a list and removes
+boiler-plate code for generating and assigning temporary variables.
 @end defmac
 
 @node Macros

  reply	other threads:[~2024-08-13 21:17 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-07-28 21:17 bug#72344: [PATCH] Add a version of cl-once-only which handles lists of forms Thuna
2024-07-29  0:39 ` Drew Adams via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-07-29 19:30   ` Thuna
2024-07-29 19:54     ` Drew Adams via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-07-29  7:09 ` Sean Whitton
2024-07-29 19:54   ` Thuna
2024-08-03  2:51     ` Sean Whitton
2024-08-03 22:40       ` Thuna
2024-08-06  1:41         ` Sean Whitton
2024-08-06  1:47           ` Sean Whitton
2024-08-09  5:44             ` Sean Whitton
2024-08-06 12:28           ` Thuna
2024-08-06 12:37             ` Sean Whitton
2024-08-13 21:17               ` Thuna [this message]
2024-08-13 21:36                 ` Drew Adams via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-08-13 22:18                   ` Thuna
2024-08-13 22:57                     ` Drew Adams via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-08-14  0:01                     ` Sean Whitton
2024-08-14  0:05                 ` Sean Whitton
2024-08-14  2:21                   ` Thuna
2024-08-14  6:09                     ` Eli Zaretskii
2024-08-14 14:14                       ` Thuna
2024-08-14 14:29                         ` Eli Zaretskii
2024-08-15  1:05                           ` Thuna
2024-08-15  6:28                             ` Eli Zaretskii
2024-08-15 15:15                               ` Thuna
2024-08-15 16:20                                 ` Eli Zaretskii
2024-08-19 16:54                                   ` Richard Stallman
2024-08-15 12:38                         ` Sean Whitton
2024-08-15 15:02                           ` Thuna
2024-08-14  9:47                     ` Sean Whitton
2024-08-06 15:52           ` Drew Adams via Bug reports for GNU Emacs, the Swiss army knife of text editors

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=874j7o2kcq.fsf@gmail.com \
    --to=thuna.cing@gmail.com \
    --cc=72344@debbugs.gnu.org \
    --cc=drew.adams@oracle.com \
    --cc=spwhitton@spwhitton.name \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).