mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-06 06:20:55 -08:00
alist-get: Add optional arg TESTFN
If TESTFN is non-nil, then it is the predicate to lookup the alist. Otherwise, use 'eq' (Bug#27584). * lisp/subr.el (alist-get): Add optional arg FULL. * lisp/emacs-lisp/map.el (map-elt, map-put): Add optional arg TESTFN. * lisp/emacs-lisp/gv.el (alist-get): Update expander. * doc/lispref/lists.texi (Association Lists): Update manual. * etc/NEWS: Announce the changes. * test/lisp/emacs-lisp/map-tests.el (test-map-put-testfn-alist) (test-map-elt-testfn): New tests.
This commit is contained in:
parent
4968aa685b
commit
76e1f7d00f
6 changed files with 51 additions and 22 deletions
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
;; Author: Nicolas Petton <nicolas@petton.fr>
|
||||
;; Keywords: convenience, map, hash-table, alist, array
|
||||
;; Version: 1.1
|
||||
;; Version: 1.2
|
||||
;; Package: map
|
||||
|
||||
;; Maintainer: emacs-devel@gnu.org
|
||||
|
|
@ -93,11 +93,13 @@ Returns the result of evaluating the form associated with MAP-VAR's type."
|
|||
((arrayp ,map-var) ,(plist-get args :array))
|
||||
(t (error "Unsupported map: %s" ,map-var)))))
|
||||
|
||||
(defun map-elt (map key &optional default)
|
||||
(defun map-elt (map key &optional default testfn)
|
||||
"Lookup KEY in MAP and return its associated value.
|
||||
If KEY is not found, return DEFAULT which defaults to nil.
|
||||
|
||||
If MAP is a list, `eql' is used to lookup KEY.
|
||||
If MAP is a list, `eql' is used to lookup KEY. Optional argument
|
||||
TESTFN, if non-nil, means use its function definition instead of
|
||||
`eql'.
|
||||
|
||||
MAP can be a list, hash-table or array."
|
||||
(declare
|
||||
|
|
@ -106,30 +108,33 @@ MAP can be a list, hash-table or array."
|
|||
(gv-letplace (mgetter msetter) `(gv-delay-error ,map)
|
||||
(macroexp-let2* nil
|
||||
;; Eval them once and for all in the right order.
|
||||
((key key) (default default))
|
||||
((key key) (default default) (testfn testfn))
|
||||
`(if (listp ,mgetter)
|
||||
;; Special case the alist case, since it can't be handled by the
|
||||
;; map--put function.
|
||||
,(gv-get `(alist-get ,key (gv-synthetic-place
|
||||
,mgetter ,msetter)
|
||||
,default)
|
||||
,default nil ,testfn)
|
||||
do)
|
||||
,(funcall do `(map-elt ,mgetter ,key ,default)
|
||||
(lambda (v) `(map--put ,mgetter ,key ,v)))))))))
|
||||
(map--dispatch map
|
||||
:list (alist-get key map default)
|
||||
:list (alist-get key map default nil testfn)
|
||||
:hash-table (gethash key map default)
|
||||
:array (if (and (>= key 0) (< key (seq-length map)))
|
||||
(seq-elt map key)
|
||||
default)))
|
||||
|
||||
(defmacro map-put (map key value)
|
||||
(defmacro map-put (map key value &optional testfn)
|
||||
"Associate KEY with VALUE in MAP and return VALUE.
|
||||
If KEY is already present in MAP, replace the associated value
|
||||
with VALUE.
|
||||
When MAP is a list, test equality with TESTFN if non-nil, otherwise use `eql'.
|
||||
TESTFN, if non-nil, means use its function definition instead of
|
||||
`eql'.
|
||||
|
||||
MAP can be a list, hash-table or array."
|
||||
`(setf (map-elt ,map ,key) ,value))
|
||||
`(setf (map-elt ,map ,key nil ,testfn) ,value))
|
||||
|
||||
(defun map-delete (map key)
|
||||
"Delete KEY from MAP and return MAP.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue