From: Stefan Monnier Date: Sat, 18 Jun 2016 04:52:58 +0000 (-0400) Subject: map.el (map-merge*): Use `map-into' at beginning rather than end X-Git-Tag: emacs-26.0.90~1840^2~219 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=44eca25a4bd1513f08ca380c9f6722c21376ac9f;p=emacs.git map.el (map-merge*): Use `map-into' at beginning rather than end * lisp/emacs-lisp/map.el (map-merge): Use `map-into' for the first map, and don't use of an intermediate alist. (map-merge-with): Same, plus use `cl-callf' to try and avoid performing 3 lookups per inner iteration. --- diff --git a/lisp/emacs-lisp/map.el b/lisp/emacs-lisp/map.el index ba15a65f5e1..b97d8b1ca64 100644 --- a/lisp/emacs-lisp/map.el +++ b/lisp/emacs-lisp/map.el @@ -43,6 +43,7 @@ ;;; Code: (require 'seq) +(eval-when-compile (require 'cl-lib)) (pcase-defmacro map (&rest args) "Build a `pcase' pattern matching map elements. @@ -282,27 +283,33 @@ MAP can be a list, hash-table or array." "Merge into a map of type TYPE all the key/value pairs in MAPS. MAP can be a list, hash-table or array." - (let (result) + (let ((result (map-into (pop maps) type))) (while maps + ;; FIXME: When `type' is `list', we get an O(N^2) behavior. + ;; For small tables, this is fine, but for large tables, we + ;; should probably use a hash-table internally which we convert + ;; to an alist in the end. (map-apply (lambda (key value) - (setf (map-elt result key) value)) - (pop maps))) - (map-into result type))) + (setf (map-elt result key) value)) + (pop maps))) + result)) (defun map-merge-with (type function &rest maps) "Merge into a map of type TYPE all the key/value pairs in MAPS. When two maps contain the same key, call FUNCTION on the two values and use the value returned by it. MAP can be a list, hash-table or array." - (let (result) + (let ((result (map-into (pop maps) type)) + (not-found (cons nil nil))) (while maps (map-apply (lambda (key value) - (setf (map-elt result key) - (if (map-contains-key result key) - (funcall function (map-elt result key) value) - value))) - (pop maps))) - (map-into result type))) + (cl-callf (lambda (old) + (if (eq old not-found) + value + (funcall function old value))) + (map-elt result key not-found))) + (pop maps))) + result)) (defun map-into (map type) "Convert the map MAP into a map of type TYPE.