aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorAndrea Corallo2019-10-11 12:18:21 -0400
committerStefan Monnier2019-10-11 12:18:21 -0400
commit421db07d061cdc493300b30646c2acd13f26d8f3 (patch)
treece05322b0458a08547371254aaad0623235fbe77 /lisp
parent65cda95be4f69c32b16364c95cb7c08971bc9397 (diff)
downloademacs-421db07d061cdc493300b30646c2acd13f26d8f3.tar.gz
emacs-421db07d061cdc493300b30646c2acd13f26d8f3.zip
* lisp/emacs-lisp/map.el (map-into) <hash-table>: Allow keyword args
(map--into-hash): New function, extracted from `map-into <hash-table>`. Speed it up a bit by using gethash instead of map-elt when we know we're accessing a hash table. * test/lisp/emacs-lisp/map-tests.el (test-map-into): Add corresponding test.
Diffstat (limited to 'lisp')
-rw-r--r--lisp/emacs-lisp/map.el31
1 files changed, 22 insertions, 9 deletions
diff --git a/lisp/emacs-lisp/map.el b/lisp/emacs-lisp/map.el
index 54e802edf4f..74927b6224f 100644
--- a/lisp/emacs-lisp/map.el
+++ b/lisp/emacs-lisp/map.el
@@ -338,7 +338,8 @@ The default implementation delegates to `map-apply'."
338 t)) 338 t))
339 339
340(defun map-merge (type &rest maps) 340(defun map-merge (type &rest maps)
341 "Merge into a map of type TYPE all the key/value pairs in MAPS." 341 "Merge into a map of type TYPE all the key/value pairs in MAPS.
342See `map-into' for all supported values of TYPE."
342 (let ((result (map-into (pop maps) type))) 343 (let ((result (map-into (pop maps) type)))
343 (while maps 344 (while maps
344 ;; FIXME: When `type' is `list', we get an O(N^2) behavior. 345 ;; FIXME: When `type' is `list', we get an O(N^2) behavior.
@@ -354,7 +355,8 @@ The default implementation delegates to `map-apply'."
354 "Merge into a map of type TYPE all the key/value pairs in MAPS. 355 "Merge into a map of type TYPE all the key/value pairs in MAPS.
355When two maps contain the same key (`eql'), call FUNCTION on the two 356When two maps contain the same key (`eql'), call FUNCTION on the two
356values and use the value returned by it. 357values and use the value returned by it.
357MAP can be a list, hash-table or array." 358MAP can be a list, hash-table or array.
359See `map-into' for all supported values of TYPE."
358 (let ((result (map-into (pop maps) type)) 360 (let ((result (map-into (pop maps) type))
359 (not-found (cons nil nil))) 361 (not-found (cons nil nil)))
360 (while maps 362 (while maps
@@ -458,17 +460,28 @@ If you want to insert an element in place, use `map-put!'."
458 (funcall function index elt)) 460 (funcall function index elt))
459 array)) 461 array))
460 462
461(cl-defmethod map-into (map (_type (eql hash-table))) 463(defun map--into-hash (map keyword-args)
462 "Convert MAP into a hash-table." 464 "Convert MAP into a hash-table.
463 ;; FIXME: Just knowing we want a hash-table is insufficient, since that 465KEYWORD-ARGS are forwarded to `make-hash-table'."
464 ;; doesn't tell us the test function to use with it! 466 (let ((ht (apply #'make-hash-table keyword-args)))
465 (let ((ht (make-hash-table :size (map-length map)
466 :test 'equal)))
467 (map-apply (lambda (key value) 467 (map-apply (lambda (key value)
468 (setf (map-elt ht key) value)) 468 (setf (gethash key ht) value))
469 map) 469 map)
470 ht)) 470 ht))
471 471
472(cl-defmethod map-into (map (_type (eql hash-table)))
473 "Convert MAP into a hash-table."
474 (map--into-hash map (list :size (map-length map) :test 'equal)))
475
476(cl-defmethod map-into (map (type (head hash-table)))
477 "Convert MAP into a hash-table.
478TYPE is a list where the car is `hash-table' and the cdr are the keyword-args
479forwarded to `make-hash-table'.
480
481Example:
482 (map-into '((1 . 3)) '(hash-table :test eql))"
483 (map--into-hash map (cdr type)))
484
472(defun map--make-pcase-bindings (args) 485(defun map--make-pcase-bindings (args)
473 "Return a list of pcase bindings from ARGS to the elements of a map." 486 "Return a list of pcase bindings from ARGS to the elements of a map."
474 (seq-map (lambda (elt) 487 (seq-map (lambda (elt)