From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Thuna Newsgroups: gmane.emacs.bugs 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 Message-ID: <874j7o2kcq.fsf@gmail.com> References: <87y15l1aj8.fsf@gmail.com> <8734nsk72i.fsf@melete.silentflame.com> <87plqw0y9j.fsf@gmail.com> <87ikwi5neo.fsf@melete.silentflame.com> <871q35mdrd.fsf@gmail.com> <871q321l7d.fsf@melete.silentflame.com> <874j7xzvgx.fsf@gmail.com> <87r0b1su7p.fsf@melete.silentflame.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="25824"; mail-complaints-to="usenet@ciao.gmane.io" Cc: 72344@debbugs.gnu.org, drew.adams@oracle.com To: Sean Whitton Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Tue Aug 13 23:20:49 2024 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1sdywf-0006TY-7X for geb-bug-gnu-emacs@m.gmane-mx.org; Tue, 13 Aug 2024 23:20:45 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sdywP-0004Lh-NU; Tue, 13 Aug 2024 17:20:29 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sdywO-0004LC-6v for bug-gnu-emacs@gnu.org; Tue, 13 Aug 2024 17:20:28 -0400 Original-Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sdywN-0006AP-Qn for bug-gnu-emacs@gnu.org; Tue, 13 Aug 2024 17:20:27 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=debbugs.gnu.org; s=debbugs-gnu-org; h=MIME-Version:Date:References:In-Reply-To:From:To:Subject; bh=sEcUldk5hTpn0DJEC6ubcdK1FmdXdhnMLlw+ujd8o7c=; b=C69ChJvIVeiRMQx37m/KfkJJSAERhFYzbJm/jSHS22CeOW/EgwiTOhLlYqsHvt0iU/F8f04ciQldrKZlu4jquRyNItleNE3BZuG8INTOtn73r/T5UhpiRsmeyzh3fPBWiMCs273+rAf/XN7/Llwt5LsOm8FrWMKqseFCyTN/HDsKv0khgH23027PeAEX+FbJOQALVHsqvkgegcnz9uLVk8UCFT/5A4hpygq3fV5sCv28oK8xvgObgsBPaVLAkBwgEzJiGc237akuajUbav0AIRf6N/p6UhwhOsiLu0F/8dc3wxF7UQSI9KFBnFbk6QQm6+OKyYZQyCSQg44YmpM9jQ==; Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1sdywv-0000vE-Lb for bug-gnu-emacs@gnu.org; Tue, 13 Aug 2024 17:21:01 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Thuna Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Tue, 13 Aug 2024 21:21:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 72344 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch Original-Received: via spool by 72344-submit@debbugs.gnu.org id=B72344.17235840073437 (code B ref 72344); Tue, 13 Aug 2024 21:21:01 +0000 Original-Received: (at 72344) by debbugs.gnu.org; 13 Aug 2024 21:20:07 +0000 Original-Received: from localhost ([127.0.0.1]:45587 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1sdyw2-0000tM-JM for submit@debbugs.gnu.org; Tue, 13 Aug 2024 17:20:07 -0400 Original-Received: from mail-ej1-f54.google.com ([209.85.218.54]:48529) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1sdyw0-0000sZ-EH for 72344@debbugs.gnu.org; Tue, 13 Aug 2024 17:20:05 -0400 Original-Received: by mail-ej1-f54.google.com with SMTP id a640c23a62f3a-a7a9185e1c0so458370766b.1 for <72344@debbugs.gnu.org>; Tue, 13 Aug 2024 14:19:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1723583905; x=1724188705; darn=debbugs.gnu.org; h=mime-version:message-id:date:references:in-reply-to:subject:cc:to :from:from:to:cc:subject:date:message-id:reply-to; bh=sEcUldk5hTpn0DJEC6ubcdK1FmdXdhnMLlw+ujd8o7c=; b=AP7pkxrJqMJA5lteJbS4TyIt9ZPUBpb0eV4FbMpKzQ5N2klr8efMmZJ2OAN3Sv4tGu g6CdDxEKcwXgf9lpg7n4TBsD0RF1e9mW7Wqm5MHQarjpvlT3NpjQbhCAmNU0iZz4uL6M dncr9N9tlGqmaV9fVw5J+GCybrofL9efvLoB82B1o/bH6WRtOYLQhNLNVQigtTFtStcX 06Q6512acu1PAHMC1FEMGpGdptR6vuZN0BVN+rkiVyVAo2r1W3aFh2w7PZJAsYqWSIRE VWrawPHZ+RLhpRJFqA38CtpVvR7yzvM3dwOyGh0kxV5Lbw6pjXxGESjllyT3eQWcrrr/ ZyXw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723583905; x=1724188705; h=mime-version:message-id:date:references:in-reply-to:subject:cc:to :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=sEcUldk5hTpn0DJEC6ubcdK1FmdXdhnMLlw+ujd8o7c=; b=qHYD5zZ2RGhkyeYRKl+6iC51tvdnXGJaRs1KroQCtUMKtKv55gM39kCVZ1Dr36pBhn a3qH6wkP0FoWwChjw3iQ87zSb7ApZdD2v0yTH+vu1cBOIf8H1wPhJeXYS0rPTy6CxvxM /zAjfuY1tp7ymWVbrn0w7IjucRXoh8rAijAqLSdx+xIcSKlNxmrlKUQjHtkszK7isUN+ XtE0KU+tNYGf2t7PrTtn1kFabJ/DfjtYjTorMs8OOv+d/SF18WcHpC7BW0Oq3M+vWB1x fur9U44yCAEFNIGNhzcUurOgXpShMgu23+ep8HYQ9crGMJ4fUYUBc9NAjwpTjkri3yqn DUBQ== X-Gm-Message-State: AOJu0YxRbyjE4d8hN3fjTYrPEoLQktwVjZDuCBQGwk4notij7z7WL1hT AKzZnGuS/j9oqAPhaoi6/JtywLqp/6+DWU1oqaaTR06mVaixkDSs X-Google-Smtp-Source: AGHT+IE1aDWm0L68p7Q6fu3Hu5jSvDrtK9yEb0CDznvXObT3xqroXpb//5Y146thkHud5f0fP4mhwA== X-Received: by 2002:a17:907:d3d2:b0:a7a:aa35:4089 with SMTP id a640c23a62f3a-a8366c34018mr46188766b.24.1723583904135; Tue, 13 Aug 2024 14:18:24 -0700 (PDT) Original-Received: from thuna-lis3 ([85.106.105.81]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a80f414e50esm98436166b.184.2024.08.13.14.18.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 13 Aug 2024 14:18:23 -0700 (PDT) In-Reply-To: <87r0b1su7p.fsf@melete.silentflame.com> X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.bugs:290092 Archived-At: --=-=-= Content-Type: text/plain >> 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?). --=-=-= Content-Type: text/x-patch Content-Disposition: inline; filename=cl-texi-second-draft.patch 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 --=-=-=--