Having searched the archives (and found lots of interesting things that
weren't what I was looking for...
If I missed archive 'gems' on this, assistance in finding them would be
appreciated.
Given the recent posting of code, I thought I would ask for the
collective c.l.l wisdom on hash table probing. Is either of these
better, and why?
(defun has-key1? (key hash-table)
(multiple-value-bind (item found?)
(gethash key hash-table)
found?))
(let ((secret (gensym)))
(defun has-key2? (key hash-table)
(not (eq secret
(gethash key hash-table secret))))
)
That leads into what I'm currently wondering about... the best way to
write the implementation of:
(stash-uniquely key value hash
(error "Frobnitz catastrophe, duplicate ~S (value ~S)
(existing value ~S)" key value item))
and what I have right now (modulo cut'n'paste errors) is:
(defmacro stash-uniquely (tag value hash-table error-expr)
(with-gensyms (found? tag-value value-value hash-table-value)
`(let ((,tag-value ,tag)
(,value-value ,value)
(,hash-table-value ,hash-table))
(multiple-value-bind (item ,found?)
(gethash ,tag-value ,hash-table-value)
(if ,found? ,error-expr)
(setf (gethash ,tag-value ,hash-table-value)
,value-value)))))
NOTE: This is anaphoric. I'm explicitly leaving 'item' exposed for use
in the error-expr. Unfortunately, if the error-expr doesn't use it, I
get an annoying warning from the compiler. I can't willy-nilly 'declare'
it to be ignored either, and I don't want to use a code-walker to
examine the error-expr (seems like way overkill).
Advice, insight, comments, etc. appreciate.
<D\'gou
Douglas Philips <····@mac.com> writes:
> (defun has-key1? (key hash-table)
> (multiple-value-bind (item found?)
> (gethash key hash-table)
> found?))
>
> (let ((secret (gensym)))
> (defun has-key2? (key hash-table)
> (not (eq secret
> (gethash key hash-table secret))))
> )
The first is what you mean. The second is an attempt at "saving" the
second value, but there will be (implementation-specific) means at
getting your SECRET. I'd go for
(defun has-key-p (key hash-table)
(nth-value 1 (gethash key hash-table)))
> NOTE: This is anaphoric. I'm explicitly leaving 'item' exposed for use
> in the error-expr. Unfortunately, if the error-expr doesn't use it, I
> get an annoying warning from the compiler. I can't willy-nilly
> 'declare' it to be ignored either, and I don't want to use a
> code-walker to examine the error-expr (seems like way overkill).
How about DECLARE IGNORABLE? It's not ideal should ITEM have
previously been declared SPECIAL, but I'd guess you probably have
bigger problems if that's true. You could just put in a reference to
ITEM in the error-expr yourself.
Christophe
--
http://www-jcsu.jesus.cam.ac.uk/~csr21/ +44 1223 510 299/+44 7729 383 757
(set-pprint-dispatch 'number (lambda (s o) (declare (special b)) (format s b)))
(defvar b "~&Just another Lisp hacker~%") (pprint #36rJesusCollegeCambridge)
Christophe Rhodes wrote:
> Douglas Philips <····@mac.com> writes:
>
>>(defun has-key1? (key hash-table)
>> (multiple-value-bind (item found?)
>> (gethash key hash-table)
>> found?))
>>
>>(let ((secret (gensym)))
>>(defun has-key2? (key hash-table)
>> (not (eq secret
>> (gethash key hash-table secret))))
>>)
>
>
> The first is what you mean. The second is an attempt at "saving" the
> second value, but there will be (implementation-specific) means at
> getting your SECRET. I'd go for
>
> (defun has-key-p (key hash-table)
> (nth-value 1 (gethash key hash-table)))
Thanks, and thanks to the private replies along that line too.
I guess "gensyms in closures" aren't inviolately secret. ;-) There's
just not standard way of def-roking them. :-O
>>NOTE: This is anaphoric. I'm explicitly leaving 'item' exposed for use
>>in the error-expr. Unfortunately, if the error-expr doesn't use it, I
>>get an annoying warning from the compiler. I can't willy-nilly
>>'declare' it to be ignored either, and I don't want to use a
>>code-walker to examine the error-expr (seems like way overkill).
>
>
> How about DECLARE IGNORABLE? It's not ideal should ITEM have
> previously been declared SPECIAL, but I'd guess you probably have
> bigger problems if that's true. You could just put in a reference to
> ITEM in the error-expr yourself.
IGNORABLE is OK. I had been thinking of having two separate macros, one
for when I wanted the old value and one for when I didn't, but that
seemed even uckier.
<D\'gou