From 3a13472adee7117e5af1249e41f6e8db9c473603 Mon Sep 17 00:00:00 2001 From: Nicolas Petton Date: Fri, 25 Mar 2016 15:09:04 +0100 Subject: [PATCH] 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. --- lisp/emacs-lisp/map.el | 36 ++++++++++-------------------------- test/automated/map-tests.el | 9 ++++++++- 2 files changed, 18 insertions(+), 27 deletions(-) diff --git a/lisp/emacs-lisp/map.el b/lisp/emacs-lisp/map.el index ec8d3d79d9f..ba15a65f5e1 100644 --- a/lisp/emacs-lisp/map.el +++ b/lisp/emacs-lisp/map.el @@ -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) diff --git a/test/automated/map-tests.el b/test/automated/map-tests.el index d145c197a4e..20cb0f6b399 100644 --- a/test/automated/map-tests.el +++ b/test/automated/map-tests.el @@ -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 -- 2.39.2