[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