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
next prev parent 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).