Add a `pcase-setq' macro
* doc/lispref/control.texi (Destructuring with pcase Patterns): Document this macro. * lisp/emacs-lisp/pcase.el (pcase-setq): New macro. This macro is the 'setq' equivalent of 'pcase-let'. * test/lisp/emacs-lisp/pcase-tests.el (pcase-setq): Test this new macro. (bug#49809).
This commit is contained in:
parent
3b5f8ab0d0
commit
2f90fa19b8
4 changed files with 94 additions and 0 deletions
|
@ -1312,6 +1312,10 @@ element of @var{list}. The bindings are performed as if by
|
|||
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
|
||||
|
|
4
etc/NEWS
4
etc/NEWS
|
@ -559,6 +559,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
|
||||
|
|
|
@ -317,6 +317,44 @@ of the elements of LIST is performed as if by `pcase-let'.
|
|||
(pcase-let* ((,(car spec) ,tmpvar))
|
||||
,@body)))))
|
||||
|
||||
;;;###autoload
|
||||
(defmacro pcase-setq (pat val &rest args)
|
||||
"Assign values to variables by destructuring with `pcase'.
|
||||
PATTERNS are normal `pcase' patterns, and VALUES are expression.
|
||||
|
||||
Evaluation happens sequentially as in `setq' (not in parallel).
|
||||
|
||||
An example: (pcase-setq `((,a) [(,b)]) '((1) [(2)]))
|
||||
|
||||
When a PATTERN doesn't match it's VALUE, the pair is silently skipped.
|
||||
|
||||
\(fn PATTERNS VALUE PATTERN VALUES ...)"
|
||||
(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))))
|
||||
|
|
|
@ -110,4 +110,52 @@
|
|||
(should-error (pcase 1
|
||||
((cl-type notatype) 'integer))))
|
||||
|
||||
(ert-deftest pcase-setq ()
|
||||
(should (equal (let (a b)
|
||||
(pcase-setq `(,a ,b) nil)
|
||||
(list a b))
|
||||
(list nil nil)))
|
||||
|
||||
(should (equal (let (a b)
|
||||
(pcase-setq `((,a) (,b)) '((1) (2)))
|
||||
(list a b))
|
||||
(list 1 2)))
|
||||
|
||||
(should (equal (list 'unset 'unset)
|
||||
(let ((a 'unset)
|
||||
(b 'unset))
|
||||
(pcase-setq `(,a ,b) nil)
|
||||
(list a b))))
|
||||
|
||||
(should (equal (let (a b)
|
||||
(pcase-setq `[,a ,b] [1 2])
|
||||
(list a b))
|
||||
'(1 2)))
|
||||
|
||||
(should (equal (let (a b)
|
||||
(pcase-setq a 1 b 2)
|
||||
(list a b))
|
||||
'(1 2)))
|
||||
|
||||
(should (= (let (a)
|
||||
(pcase-setq a 1 `(,a) '(2))
|
||||
a)
|
||||
2))
|
||||
|
||||
(should (equal (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))
|
||||
'(nil [1 2 3] 4)))
|
||||
|
||||
(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.
|
||||
|
|
Loading…
Add table
Reference in a new issue