unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Okam via "Bug reports for GNU Emacs, the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org>
To: Stefan Monnier <monnier@iro.umontreal.ca>
Cc: 49809@debbugs.gnu.org
Subject: bug#49809: [PATCH] Add macro 'pcase-setq'
Date: Fri, 06 Aug 2021 22:33:36 +0000	[thread overview]
Message-ID: <e0e0e5f4-1235-e228-6417-0bad36c96652@protonmail.com> (raw)
In-Reply-To: <jwvwnp0su3m.fsf-monnier+emacs@gnu.org>

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

On 8/4/21 7:06 PM, Stefan Monnier wrote:
> I don't think we should try and combine them: it's not worth the
> code complexity.  Personally I'd even restrict the calling convention to
> (pcase-setq PAT VAL), but if you want to accept the more general case
> with multiple PAT+VAL, I'd prefer expanding it to a (progn (pcase-setq
> PAT1 VAL1) ...).  I think the resulting code would be simpler/cleaner.

Done.

>> +@defmac pcase-setq pattern value@dots{}
>> +Bind variables to values in a @code{setq} form, destructuring each
>> +@var{value} according to its respective @var{pattern}.
>> +@end defmac
>
> I prefer keeping "bind" for the case where we create new variables
> (i.e. let-bindings) rather than for assignments.

This was changed to the phrase "assign values to variables".

>
> Looks good.  But could you add a few corresponding tests to
> `test/lisp/emacs-lisp/pcase-tests.el`, including tests for things like
>
>      (pcase-setq `(,a ,b) nil)

Added with others. Do you think that the added tests are sufficient?

Thank you.



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: v2-0001-Add-macro-pcase-setq.patch --]
[-- Type: text/x-patch; name=v2-0001-Add-macro-pcase-setq.patch, Size: 4881 bytes --]

From 391bdb4efc25b1c3c521b27d6203a5de173a2d14 Mon Sep 17 00:00:00 2001
From: Earl Hyatt <okamsn@protonmail.com>
Date: Sun, 1 Aug 2021 12:33:14 -0400
Subject: [PATCH v2] Add macro 'pcase-setq'

* lisp/emacs-lisp/pcase.el (pcase-setq): New macro.

This macro is the 'setq' equivalent of 'pcase-let'.

* doc/lispref/control.texi (Destructuring with pcase Patterns):
Document this macro.

* test/lisp/emacs-lisp/pcase-tests.el (pcase-setq): Test this new macro.
---
 doc/lispref/control.texi            |  5 ++++
 etc/NEWS                            |  4 ++++
 lisp/emacs-lisp/pcase.el            | 31 +++++++++++++++++++++++++
 test/lisp/emacs-lisp/pcase-tests.el | 36 +++++++++++++++++++++++++++++
 4 files changed, 76 insertions(+)

diff --git a/doc/lispref/control.texi b/doc/lispref/control.texi
index 5026d0a4d7..6e4a5234e2 100644
--- a/doc/lispref/control.texi
+++ b/doc/lispref/control.texi
@@ -1312,6 +1312,11 @@ Destructuring with pcase Patterns
 up being equivalent to @code{dolist} (@pxref{Iteration}).
 @end defmac
 
+@defmac pcase-setq pattern value@dots{}
+Assign values to variables in a @code{setq} form,
+destructuring each @var{value} according to its respective
+@var{pattern}.
+@end defmac
 
 @node Iteration
 @section Iteration
diff --git a/etc/NEWS b/etc/NEWS
index 95a2c87d05..0f11caf512 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -553,6 +553,10 @@ The new 'cl-type' pattern compares types using 'cl-typep', which allows
 comparing simple types like '(cl-type integer)', as well as forms like
 '(cl-type (integer 0 10))'.
 
+*** New macro 'pcase-setq'
+This macro is the 'setq' equivalent of 'pcase-let', which allows for
+destructuring patterns in a 'setq' form.
+
 +++
 ** profiler.el
 The results displayed by 'profiler-report' now have the usage figures
diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el
index 006517db75..14af70a65b 100644
--- a/lisp/emacs-lisp/pcase.el
+++ b/lisp/emacs-lisp/pcase.el
@@ -317,6 +317,37 @@ pcase-dolist
          (pcase-let* ((,(car spec) ,tmpvar))
            ,@body)))))
 
+;;;###autoload
+(defmacro pcase-setq (pat val &rest args)
+  "Assign values to variables by destructuring with `pcase'.
+
+\(fn PATTERN VALUE PATTERN VALUE ...)"
+  (declare (debug (&rest [pcase-PAT form])))
+  (cond
+   (args
+    (let ((arg-length (length args)))
+      (unless (= 0 (mod arg-length 2))
+        (signal 'wrong-number-of-arguments
+                (list 'pcase-setq (+ 2 arg-length)))))
+    (let ((result))
+      (while args
+        (push `(pcase-setq ,(pop args) ,(pop args))
+              result))
+      `(progn
+         (pcase-setq ,pat ,val)
+         ,@(nreverse result))))
+   ((pcase--trivial-upat-p pat)
+    `(setq ,pat ,val))
+   (t
+    (pcase-compile-patterns
+     val
+     (list (cons pat
+                 (lambda (varvals &rest _)
+                   `(setq ,@(mapcan (lambda (varval)
+                                      (let ((var (car varval))
+                                            (val (cadr varval)))
+                                        (list var val)))
+                                    varvals)))))))))
 
 (defun pcase--trivial-upat-p (upat)
   (and (symbolp upat) (not (memq upat pcase--dontcare-upats))))
diff --git a/test/lisp/emacs-lisp/pcase-tests.el b/test/lisp/emacs-lisp/pcase-tests.el
index 02d3878ad0..c53648383a 100644
--- a/test/lisp/emacs-lisp/pcase-tests.el
+++ b/test/lisp/emacs-lisp/pcase-tests.el
@@ -110,4 +110,40 @@ pcase-tests-cl-type
   (should-error (pcase 1
                   ((cl-type notatype) 'integer))))
 
+(ert-deftest pcase-setq ()
+  (should (equal (list nil nil)
+                 (let (a b)
+                   (pcase-setq `(,a ,b) nil)
+                   (list a b))))
+
+  (should (equal '(1 2)
+                 (let (a b)
+                   (pcase-setq `[,a ,b] [1 2])
+                   (list a b))))
+
+  (should (equal '(1 2)
+                 (let (a b)
+                   (pcase-setq a 1 b 2)
+                   (list a b))))
+
+  (should (= 2 (let (a)
+                 (pcase-setq a 1 `(,a) '(2))
+                 a)))
+
+  (should (equal '(nil [1 2 3] 4)
+                 (let (array list-item array-copy)
+                   (pcase-setq (or `(,list-item) array) [1 2 3]
+                               array-copy array
+                               ;; This re-sets `array' to nil.
+                               (or `(,list-item) array) '(4))
+                   (list array array-copy list-item))))
+
+  (let ((a nil))
+    (should-error (pcase-setq a 1 b)
+                  :type '(wrong-number-of-arguments))
+    (should (eq a nil)))
+
+  (should-error (pcase-setq a)
+                :type '(wrong-number-of-arguments)))
+
 ;;; pcase-tests.el ends here.
-- 
2.25.1


  parent reply	other threads:[~2021-08-06 22:33 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-08-01 17:20 bug#49809: [PATCH] Add macro 'pcase-setq' Okam via Bug reports for GNU Emacs, the Swiss army knife of text editors
2021-08-04  7:14 ` Lars Ingebrigtsen
2021-08-04 23:06 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2021-08-05  1:02   ` Michael Heerdegen
2021-08-05 13:34     ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2021-08-05 15:00       ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2021-08-06  1:42       ` Michael Heerdegen
2021-08-06  4:07         ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2021-08-06  4:28           ` Michael Heerdegen
2021-08-06 22:33   ` Okam via Bug reports for GNU Emacs, the Swiss army knife of text editors [this message]
2021-08-07  2:11     ` Michael Heerdegen
2021-08-11 21:57       ` Lars Ingebrigtsen
2021-08-12  6:13         ` Michael Heerdegen
2021-08-12 12:11           ` Okam via Bug reports for GNU Emacs, the Swiss army knife of text editors
2021-08-12 15:06           ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2021-08-13  2:55             ` Michael Heerdegen
2021-08-13  5:17               ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2021-08-13  5:26                 ` Michael Heerdegen
2021-08-07 15:42     ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2021-08-09  0:28       ` Michael Heerdegen
2021-08-09 12:51         ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2021-08-10  3:13           ` Michael Heerdegen
2021-08-12 16:13             ` Stefan Monnier 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=e0e0e5f4-1235-e228-6417-0bad36c96652@protonmail.com \
    --to=bug-gnu-emacs@gnu.org \
    --cc=49809@debbugs.gnu.org \
    --cc=monnier@iro.umontreal.ca \
    --cc=okamsn@protonmail.com \
    /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).