(require 'pcase) (defmacro pcase-setq (pat val &rest args) "Assign values to variables by destructuring with `pcase'. Each PATTERN and VALUE is handled sequentially. PATTERN is a normal `pcase' pattern. VALUE is an expression. If a PATTERN does not match its VALUE, then the variables in that PATTERN are set to nil. \(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 (let* ((pcase-setq-unique-vars nil) (expansion (pcase-compile-patterns val (list (cons pat (lambda (varvals &rest _) (let ((flat-var-val-list)) (dolist (varval varvals) (let ((var (car varval)) (val (cadr varval))) (unless (memq var pcase-setq-unique-vars) (push var pcase-setq-unique-vars)) (push var flat-var-val-list) (push val flat-var-val-list))) `(setq ,@(nreverse flat-var-val-list))))))))) `(progn (setq ,@(mapcan (lambda (x) (list x nil)) pcase-setq-unique-vars)) ,expansion)))))