From: Douglas Philips
Subject: Hash table probe...
Date: 
Message-ID: <3F6B370A.5000102@mac.com>
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

From: Christophe Rhodes
Subject: Re: Hash table probe...
Date: 
Message-ID: <sqoexgofeu.fsf@lambda.jcn.srcf.net>
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)
From: Douglas Philips
Subject: Re: Hash table probe...
Date: 
Message-ID: <3F6F37F2.5060904@mac.com>
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