Fix map-put and map-delete for alists (Bug#23105)

* lisp/emacs-lisp/map.el (map-put): Do not bind the evaluated place
expression to a new symbol.
* test/lisp/emacs-lisp/map-tests.el: Add a regression test.
This commit is contained in:
Nicolas Petton 2016-03-25 15:09:04 +01:00
parent 422c3dadce
commit 3a13472ade
2 changed files with 18 additions and 27 deletions

View file

@ -123,33 +123,26 @@ MAP can be a list, hash-table or array."
default)))
(defmacro map-put (map key value)
"Associate KEY with VALUE in MAP and return MAP.
"Associate KEY with VALUE in MAP and return VALUE.
If KEY is already present in MAP, replace the associated value
with VALUE.
MAP can be a list, hash-table or array."
(macroexp-let2 nil map map
`(progn
(setf (map-elt ,map ,key) ,value)
,map)))
`(setf (map-elt ,map ,key) ,value))
(defmacro map-delete (map key)
(defun map-delete (map key)
"Delete KEY from MAP and return MAP.
No error is signaled if KEY is not a key of MAP. If MAP is an
array, store nil at the index KEY.
MAP can be a list, hash-table or array."
(declare (debug t))
(gv-letplace (mgetter msetter) `(gv-delay-error ,map)
(macroexp-let2 nil key key
`(if (not (listp ,mgetter))
(map--delete ,mgetter ,key)
;; The alist case is special, since it can't be handled by the
;; map--delete function.
(setf (alist-get ,key (gv-synthetic-place ,mgetter ,msetter)
nil t)
nil)
,mgetter))))
(map--dispatch map
:list (setf (alist-get key map nil t) nil)
:hash-table (remhash key map)
:array (and (>= key 0)
(<= key (seq-length map))
(aset map key nil)))
map)
(defun map-nested-elt (map keys &optional default)
"Traverse MAP using KEYS and return the looked up value or DEFAULT if nil.
@ -337,15 +330,6 @@ MAP can be a list, hash-table or array."
(cdr pair)))
map))
(defun map--delete (map key)
(map--dispatch map
:list (error "No place to remove the mapping for %S" key)
:hash-table (remhash key map)
:array (and (>= key 0)
(<= key (seq-length map))
(aset map key nil)))
map)
(defun map--apply-hash-table (function map)
"Private function used to apply FUNCTION over MAP, MAP being a hash-table."
(let (result)

View file

@ -87,9 +87,16 @@ Evaluate BODY for each created map.
(let ((vec [3 4 5]))
(should-error (setf (map-elt vec 3) 6))))
(ert-deftest test-map-put-alist-new-key ()
"Regression test for Bug#23105."
(let ((alist '((0 . a))))
(map-put alist 2 'b)
(should (eq (map-elt alist 2)
'b))))
(ert-deftest test-map-put-return-value ()
(let ((ht (make-hash-table)))
(should (eq (map-put ht 'a 'hello) ht))))
(should (eq (map-put ht 'a 'hello) 'hello))))
(ert-deftest test-map-delete ()
(with-maps-do map