1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-23 22:20:24 -08:00

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.
This commit is contained in:
Stefan Monnier 2016-06-18 00:52:58 -04:00
parent 574cd99692
commit 44eca25a4b

View file

@ -43,6 +43,7 @@
;;; Code: ;;; Code:
(require 'seq) (require 'seq)
(eval-when-compile (require 'cl-lib))
(pcase-defmacro map (&rest args) (pcase-defmacro map (&rest args)
"Build a `pcase' pattern matching map elements. "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. "Merge into a map of type TYPE all the key/value pairs in MAPS.
MAP can be a list, hash-table or array." MAP can be a list, hash-table or array."
(let (result) (let ((result (map-into (pop maps) type)))
(while maps (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) (map-apply (lambda (key value)
(setf (map-elt result key) value)) (setf (map-elt result key) value))
(pop maps))) (pop maps)))
(map-into result type))) result))
(defun map-merge-with (type function &rest maps) (defun map-merge-with (type function &rest maps)
"Merge into a map of type TYPE all the key/value pairs in 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 When two maps contain the same key, call FUNCTION on the two
values and use the value returned by it. values and use the value returned by it.
MAP can be a list, hash-table or array." 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 (while maps
(map-apply (lambda (key value) (map-apply (lambda (key value)
(setf (map-elt result key) (cl-callf (lambda (old)
(if (map-contains-key result key) (if (eq old not-found)
(funcall function (map-elt result key) value) value
value))) (funcall function old value)))
(map-elt result key not-found)))
(pop maps))) (pop maps)))
(map-into result type))) result))
(defun map-into (map type) (defun map-into (map type)
"Convert the map MAP into a map of type TYPE. "Convert the map MAP into a map of type TYPE.