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