summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp
diff options
context:
space:
mode:
authorNicolas Petton <nicolas@petton.fr>2015-06-02 22:13:38 +0200
committerNicolas Petton <nicolas@petton.fr>2015-06-02 22:19:48 +0200
commit988d72118687758af6c2b7c56c80056630d428ca (patch)
tree55054d3d1dc8bf9d4fe9f347a4c25a0bf3a507c8 /lisp/emacs-lisp
parent6591d361390daa6c36045b82acb9ea548687879c (diff)
downloademacs-988d72118687758af6c2b7c56c80056630d428ca.tar.gz
emacs-988d72118687758af6c2b7c56c80056630d428ca.tar.bz2
emacs-988d72118687758af6c2b7c56c80056630d428ca.zip
Add a pcase pattern for maps and `map-let' based on it
* lisp/emacs-lisp/map.el (map-let): New macro. (map--make-pcase-bindings, map--make-pcase-patterns): New functions. * test/automated/map-tests.el: New test for `map-let'.
Diffstat (limited to 'lisp/emacs-lisp')
-rw-r--r--lisp/emacs-lisp/map.el35
1 files changed, 35 insertions, 0 deletions
diff --git a/lisp/emacs-lisp/map.el b/lisp/emacs-lisp/map.el
index 8801b2aba7a..dea2abcb0e8 100644
--- a/lisp/emacs-lisp/map.el
+++ b/lisp/emacs-lisp/map.el
@@ -44,6 +44,24 @@
(require 'seq)
+(pcase-defmacro map (&rest args)
+ "pcase pattern matching map elements.
+Matches if the object is a map (list, hash-table or array), and
+binds values from ARGS to the corresponding element of the map.
+
+ARGS can be an alist of key/binding pairs of a list of keys."
+ `(and (pred map-p)
+ ,@(map--make-pcase-bindings args)))
+
+(defmacro map-let (args map &rest body)
+ "Bind the variables in ARGS to the elements of MAP then evaluate BODY.
+
+ARGS can be an alist of key/binding pairs or a list of keys. MAP
+can be a list, hash-table or array."
+ (declare (indent 2) (debug t))
+ `(pcase-let ((,(map--make-pcase-patterns args) ,map))
+ ,@body))
+
(defun map-elt (map key &optional default)
"Perform a lookup in MAP of KEY and return its associated value.
If KEY is not found, return DEFAULT which defaults to nil.
@@ -331,5 +349,22 @@ If KEY is not found, return DEFAULT which defaults to nil."
map)
ht))
+(defun map--make-pcase-bindings (args)
+ "Return a list of pcase bindings from ARGS to the elements of a map."
+ (seq-map (lambda (elt)
+ (if (consp elt)
+ `(app (pcase--flip map-elt ',(car elt)) ,(cdr elt))
+ `(app (pcase--flip map-elt ',elt) ,elt)))
+ args))
+
+(defun map--make-pcase-patterns (args)
+ "Return a list of `(map ...)' pcase patterns built from ARGS."
+ (cons 'map
+ (seq-map (lambda (elt)
+ (if (and (consp elt) (eq 'map (car elt)))
+ (map--make-pcase-patterns elt)
+ elt))
+ args)))
+
(provide 'map)
;;; map.el ends here