[alexandria-devel] :TEST and :KEY for maphash-{keys, values}: in the spirit of 14.1.2.2

Samium Gromoff _deepfire at feelingofgreen.ru
Mon Jan 28 03:06:49 UTC 2008


In the spirit of `14.1.2.2 Lists as Sets', that is, in order to facilitate
use of hash tables as sets, it seems to make sense to extend MAPHASH-KEYS
and MAPHASH-VALUES to accept :TEST, :TEST-NOT and :KEY, as specified by
`17.2.1 Satisfying a Two-Argument Test', with a difference of making tests
accept a single parameter.

A possible implementation (derived from SBCL sources) is as follows:

(defmacro apply-key (key element)
  `(if ,key
       (funcall ,key ,element)
       ,element))

(defmacro satisfies-the-test (elt)
  (with-gensyms (key-tmp)
    `(let ((,key-tmp (apply-key key ,elt)))
       (cond (testp (funcall test ,key-tmp))
             (notp (not (funcall test-not ,key-tmp)))
             (t t)))))

(declaim (inline maphash-keys))
(defun maphash-keys (function table &key key (test nil testp) (test-not nil notp))
  "Like MAPHASH, but calls FUNCTION with each key in the hash table TABLE."
  (when (and testp notp)
    (error ":TEST and :TEST-NOT were both supplied."))
  (maphash (lambda (k v)
             (declare (ignore v))
             (when (satisfies-the-test k)
               (funcall function k)))
           table))

(declaim (inline maphash-values))
(defun maphash-values (function table &key key (test nil testp) (test-not nil notp))
  "Like MAPHASH, but calls FUNCTION with each value in the hash table TABLE."
  (when (and testp notp)
    (error ":TEST and :TEST-NOT were both supplied."))
  (maphash (lambda (k v)
             (declare (ignore k))
             (when (satisfies-the-test k)
               (funcall function v)))
           table))

There is also a question of whether it is desirable to extend in a similar
manner MAPHASH itself (under a different name), so as to make it accept :KEY-KEY,
:VALUE-KEY, :KEY-TEST, :VALUE-TEST, which would make the extension protocol
usable in a wider range of scenarios.

regards, Samium Gromoff



More information about the alexandria-devel mailing list