* [bug #22022] hashx-set! and -ref
@ 2008-01-14 22:40 Gregory Marton
2008-01-17 21:52 ` Neil Jerram
2008-01-17 23:13 ` Neil Jerram
0 siblings, 2 replies; 13+ messages in thread
From: Gregory Marton @ 2008-01-14 22:40 UTC (permalink / raw)
To: Gregory Marton, bug-guile
URL:
<http://savannah.gnu.org/bugs/?22022>
Summary: hashx-set! and -ref
Project: Guile
Submitted by: gremio
Submitted on: Monday 01/14/2008 at 22:40
Category: None
Severity: 3 - Normal
Item Group: None
Status: None
Privacy: Public
Assigned to: None
Open/Closed: Open
Discussion Lock: Any
_______________________________________________________
Details:
Hashing using ones own hash functions does not survive a hash resize.
If the assoc function returns #t, a segfault or bus error results.
A patch to the test suite demonstrating these and testing a few other things
is attached.
As an enhancement request, it would be nice for the common case to be able to
pass a hash-function argument and assoc to make-hash-table or to have a
(make-hashx-table hash assoc [size]), and in either case to remember the hash
function so that resize works correctly.
Thanks,
Grem
_______________________________________________________
File Attachments:
-------------------------------------------------------
Date: Monday 01/14/2008 at 22:40 Name: hash.test.patch Size: 7kB By:
gremio
<http://savannah.gnu.org/bugs/download.php?file_id=14801>
_______________________________________________________
Reply to this item at:
<http://savannah.gnu.org/bugs/?22022>
_______________________________________________
Message sent via/by Savannah
http://savannah.gnu.org/
^ permalink raw reply [flat|nested] 13+ messages in thread
* [bug #22022] hashx-set! and -ref
2008-01-14 22:40 [bug #22022] hashx-set! and -ref Gregory Marton
@ 2008-01-17 21:52 ` Neil Jerram
2008-01-17 21:54 ` Gregory Marton
2008-01-17 21:57 ` Neil Jerram
2008-01-17 23:13 ` Neil Jerram
1 sibling, 2 replies; 13+ messages in thread
From: Neil Jerram @ 2008-01-17 21:52 UTC (permalink / raw)
To: Neil Jerram, Gregory Marton, bug-guile
Follow-up Comment #1, bug #22022 (project guile):
I think I have a fix for the segfault, but now I'm seeing several other test
failures. Here's one...
(pass-if (let ((table (make-hash-table)))
(hashx-set! (lambda (k v) 1) assoc table 'foo 'bar)
(equal?
'bar (hashx-ref (lambda (k v) 1) assoc table 'baz))))
This one is wrong, isn't it? It sets an entry with key 'foo, then queries
the entry with key 'baz. So the result, correctly, is #f. What was your
intention here?
_______________________________________________________
Reply to this item at:
<http://savannah.gnu.org/bugs/?22022>
_______________________________________________
Message sent via/by Savannah
http://savannah.gnu.org/
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [bug #22022] hashx-set! and -ref
2008-01-17 21:52 ` Neil Jerram
@ 2008-01-17 21:54 ` Gregory Marton
2008-01-17 23:02 ` Neil Jerram
2008-01-17 21:57 ` Neil Jerram
1 sibling, 1 reply; 13+ messages in thread
From: Gregory Marton @ 2008-01-17 21:54 UTC (permalink / raw)
To: Neil Jerram; +Cc: bug-guile, Neil Jerram
Ack. I think I meant to replace assoc as well, with something like (lambda
(k alist) (cdar alist)). My intention was to get it to give me back 'bar
because the hash functions would accept anything, rather than because it
was "right" in any sense.
Sorry,
Grem
> Follow-up Comment #1, bug #22022 (project guile):
>
> I think I have a fix for the segfault, but now I'm seeing several other test
> failures. Here's one...
>
> (pass-if (let ((table (make-hash-table)))
> (hashx-set! (lambda (k v) 1) assoc table 'foo 'bar)
> (equal?
> 'bar (hashx-ref (lambda (k v) 1) assoc table 'baz))))
>
> This one is wrong, isn't it? It sets an entry with key 'foo, then queries
> the entry with key 'baz. So the result, correctly, is #f. What was your
> intention here?
>
>
> _______________________________________________________
>
> Reply to this item at:
>
> <http://savannah.gnu.org/bugs/?22022>
>
> _______________________________________________
> Message sent via/by Savannah
> http://savannah.gnu.org/
>
>
--
------ __@ Gregory A. Marton http://csail.mit.edu/~gremio/
--- _`\<,_ .
-- (*)/ (*) A closed mouth gathers no foot.
~~~~~~~~~~~~~~~~-~~~~~~~~_~~~_~~~~~v~~~~^^^^~~~~~--~~~~~~~~~~~~~~~++~~~~~~~
^ permalink raw reply [flat|nested] 13+ messages in thread
* [bug #22022] hashx-set! and -ref
2008-01-17 21:52 ` Neil Jerram
2008-01-17 21:54 ` Gregory Marton
@ 2008-01-17 21:57 ` Neil Jerram
2008-01-17 22:01 ` Gregory Marton
2008-01-17 22:45 ` Neil Jerram
1 sibling, 2 replies; 13+ messages in thread
From: Neil Jerram @ 2008-01-17 21:57 UTC (permalink / raw)
To: Neil Jerram, Gregory Marton, bug-guile
Follow-up Comment #2, bug #22022 (project guile):
Another one:
(pass-if (equal? "#<hash-table 34/61>"
(with-output-to-string (lambda () (write table)))))))
Actual output here has 33 instead of 34. I believe 33 is correct, because
the additions to the hash table run from 2 up to 34, not from 1 up to 34.
Agree?
_______________________________________________________
Reply to this item at:
<http://savannah.gnu.org/bugs/?22022>
_______________________________________________
Message sent via/by Savannah
http://savannah.gnu.org/
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [bug #22022] hashx-set! and -ref
2008-01-17 21:57 ` Neil Jerram
@ 2008-01-17 22:01 ` Gregory Marton
2008-01-17 22:45 ` Neil Jerram
1 sibling, 0 replies; 13+ messages in thread
From: Gregory Marton @ 2008-01-17 22:01 UTC (permalink / raw)
To: Neil Jerram; +Cc: bug-guile, Neil Jerram
Thanks, yes. I initially had a one in there. Hmmm... it doesn't matter.
33 is enough to trigger resize.
Thanks,
Grem
> Follow-up Comment #2, bug #22022 (project guile):
>
> Another one:
>
> (pass-if (equal? "#<hash-table 34/61>"
> (with-output-to-string (lambda () (write table)))))))
>
> Actual output here has 33 instead of 34. I believe 33 is correct, because
> the additions to the hash table run from 2 up to 34, not from 1 up to 34.
>
> Agree?
>
> _______________________________________________________
>
> Reply to this item at:
>
> <http://savannah.gnu.org/bugs/?22022>
>
> _______________________________________________
> Message sent via/by Savannah
> http://savannah.gnu.org/
>
>
>
>
--
------ __@ Gregory A. Marton http://csail.mit.edu/~gremio/
--- _`\<,_ .
-- (*)/ (*) Teach you backwards to speak I can.
~~~~~~~~~~~~~~~~-~~~~~~~~_~~~_~~~~~v~~~~^^^^~~~~~--~~~~~~~~~~~~~~~++~~~~~~~
^ permalink raw reply [flat|nested] 13+ messages in thread
* [bug #22022] hashx-set! and -ref
2008-01-17 21:57 ` Neil Jerram
2008-01-17 22:01 ` Gregory Marton
@ 2008-01-17 22:45 ` Neil Jerram
2008-01-18 0:22 ` Gregory Marton
2008-01-29 22:28 ` Neil Jerram
1 sibling, 2 replies; 13+ messages in thread
From: Neil Jerram @ 2008-01-17 22:45 UTC (permalink / raw)
To: Neil Jerram, Gregory Marton, bug-guile
Follow-up Comment #3, bug #22022 (project guile):
And here are all the remaining ones. I've added a (pk ...) in each case, so
the output from make check shows what the actual hash?-ref value was.
;;; (#f)
FAIL: hash.test: auto-resizing hashx: (equal? (quote eq) (pk (hashq-ref table
4)))
;;; (#f)
FAIL: hash.test: auto-resizing hashx: (equal? (quote equal) (pk (hashx-ref
hash equal? table 1/32)))
;;; (#f)
FAIL: hash.test: auto-resizing hashx: (equal? (quote eqv) (pk (hashx-ref
hashv eqv? table 1/33)))
;;; (#f)
FAIL: hash.test: auto-resizing hashx: (equal? (quote eq) (pk (hashx-ref hashq
eq? table 34)))
These cases, together with the neighbouring ones that happen to pass, are
actually out of scope, because the manual says (5.6.12.2 Hash Table
Reference):
-----------manual------------
Like the association list functions, the hash table functions come in
several varieties, according to the equality test used for the keys.
Plain `hash-' functions use `equal?', `hashq-' functions use `eq?',
`hashv-' functions use `eqv?', and the `hashx-' functions use an
application supplied test.
A single `make-hash-table' creates a hash table suitable for use
with any set of functions, but it's imperative that just one set is
then used consistently, or results will be unpredictable.
-----------manual------------
The rationale for this is what happens when a hash table is resized. When
that happens, the new hash buckets (vector indices) are recalculated, for all
existing entries in the table, using the hash function that was specified on
the call that caused the resize. If that hash function is different from the
hash that is later used to try to query particular entries, Guile can look in
the wrong bucket, and the expected entry won't be found.
There's another case, too, where a rehash is done following GC, using a hash
function that was stored at some point in the hashtable data structure. But I
haven't got right into that, because I think we already have enough to rule
these test cases invalid.
What do you think?
_______________________________________________________
Reply to this item at:
<http://savannah.gnu.org/bugs/?22022>
_______________________________________________
Message sent via/by Savannah
http://savannah.gnu.org/
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [bug #22022] hashx-set! and -ref
2008-01-17 21:54 ` Gregory Marton
@ 2008-01-17 23:02 ` Neil Jerram
2008-01-18 0:25 ` Gregory Marton
0 siblings, 1 reply; 13+ messages in thread
From: Neil Jerram @ 2008-01-17 23:02 UTC (permalink / raw)
To: Gregory Marton; +Cc: bug-guile
Gregory Marton <gremio@mit.edu> writes:
> Ack. I think I meant to replace assoc as well, with something like
> (lambda (k alist) (cdar alist)).
That wouldn't be assoc-like. (lambda (k al) (car al)) accesses the
correct level of alist structure, but would fault in the case where al
is empty.
So perhaps: (lambda (k al) (and (not (null? al)) (car al))). With
this, the test passes - are you happy with that?
Thanks,
Neil
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [bug #22022] hashx-set! and -ref
2008-01-14 22:40 [bug #22022] hashx-set! and -ref Gregory Marton
2008-01-17 21:52 ` Neil Jerram
@ 2008-01-17 23:13 ` Neil Jerram
2008-01-18 0:30 ` Gregory Marton
1 sibling, 1 reply; 13+ messages in thread
From: Neil Jerram @ 2008-01-17 23:13 UTC (permalink / raw)
To: Gregory Marton, bug-guile
Gregory Marton <INVALID.NOREPLY@gnu.org> writes:
> As an enhancement request, it would be nice for the common case to be able to
> pass a hash-function argument and assoc to make-hash-table or to have a
> (make-hashx-table hash assoc [size]), and in either case to remember the hash
> function so that resize works correctly.
Last email on this topic for tonight...!
Note that anyone wanting to implement this "saner" interface can
straightforwardly do so in Scheme:
(define hash-table-hash-fn (make-object-property))
(define hash-table-assoc-fn (make-object-property))
(define (make-hashx-table hash assoc . args)
(let ((t (apply make-hash-table args)))
(set! (hash-table-hash-fn t) hash)
(set! (hash-table-assoc-fn t) assoc)
t))
(define (hashx-table-ref t key)
(hashx-ref (hash-table-hash-fn t) (hash-table-assoc-fn t) t key))
etc.
Regards,
Neil
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [bug #22022] hashx-set! and -ref
2008-01-17 22:45 ` Neil Jerram
@ 2008-01-18 0:22 ` Gregory Marton
2008-01-29 22:28 ` Neil Jerram
1 sibling, 0 replies; 13+ messages in thread
From: Gregory Marton @ 2008-01-18 0:22 UTC (permalink / raw)
To: Neil Jerram; +Cc: bug-guile, Neil Jerram
> What do you think?
I didn't read that part of the spec, so I was confused, and I'll grant that
the cases may be out of scope.
Moreover, I think the hash specification is problematic.
(a) the representation seems to wish to hide the current size of the
hash vector, or at least that would be sensible, but it is exposed
in the printout and as an argument to the hash-function supplied to
hashx. The point at which the hash is resized is unpredictable from
the user's point of view. This is three flavors of rep exposure.
(b) if, as the doc says, "it's imperative that just one set is then used
consistently, or results will be unpredictable", then it makes sense
to enforce this. A common way to enforce it is to ask for the hash
function just once, at creation time. By requiring it everywhere,
we force the user to expose a representation, the hash function and
equality predicate, between one part of their program and another.
(c) the assoc requirement is a rep exposure of a third sort -- it exposes
the fact that buckets are alists. There is no reason for the user to
know this, and there is no reason it should be so. If a future
implementation wants to do something else, say hash with another
hash, they will have to emulate assoc-ability to make this API work.
Moreover, this forces the user to write the assoc function on top of
their equality predicate, which is neither fast (it's Scheme instead
of C) nor DRY (Don't Repeat Yourself -- a principle of not
duplicating code).
If the current set of decisions seems self-consistent and useful to the
community, then I guess I'd submit an enhancement request, for a new set of
fast functions:
(make-hashf-table one-arg-hash-function equality-predicate [size])
(hashf-set! hashf-table 'key value)
(hashf-ref hashf-table 'key [default])
(hashf-remove! hashf-table 'key)
(hashf-size hashf-table) ===> the number of keys stored
... [clear get-handle create-handle for-each for-each-handle map->list
"f" for the functions it stores.
Thanks,
Grem
--
------ __@ Gregory A. Marton http://csail.mit.edu/~gremio/
--- _`\<,_ .
-- (*)/ (*) Contents may have settled out of court.
~~~~~~~~~~~~~~~~-~~~~~~~~_~~~_~~~~~v~~~~^^^^~~~~~--~~~~~~~~~~~~~~~++~~~~~~~
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [bug #22022] hashx-set! and -ref
2008-01-17 23:02 ` Neil Jerram
@ 2008-01-18 0:25 ` Gregory Marton
0 siblings, 0 replies; 13+ messages in thread
From: Gregory Marton @ 2008-01-18 0:25 UTC (permalink / raw)
To: Neil Jerram; +Cc: bug-guile
Yes, thank you. Apologies again for my carelessness.
Grem
> Gregory Marton <gremio@mit.edu> writes:
>
>> Ack. I think I meant to replace assoc as well, with something like
>> (lambda (k alist) (cdar alist)).
>
> That wouldn't be assoc-like. (lambda (k al) (car al)) accesses the
> correct level of alist structure, but would fault in the case where al
> is empty.
>
> So perhaps: (lambda (k al) (and (not (null? al)) (car al))). With
> this, the test passes - are you happy with that?
>
> Thanks,
> Neil
>
>
--
------ __@ Gregory A. Marton http://csail.mit.edu/~gremio/
--- _`\<,_ .
-- (*)/ (*) There's no place like /home
~~~~~~~~~~~~~~~~-~~~~~~~~_~~~_~~~~~v~~~~^^^^~~~~~--~~~~~~~~~~~~~~~++~~~~~~~
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [bug #22022] hashx-set! and -ref
2008-01-17 23:13 ` Neil Jerram
@ 2008-01-18 0:30 ` Gregory Marton
0 siblings, 0 replies; 13+ messages in thread
From: Gregory Marton @ 2008-01-18 0:30 UTC (permalink / raw)
To: Neil Jerram; +Cc: bug-guile
Thank you. I did something far less elegant already, but it's good to have
this. I should also read all of my email before responding. :-)
Best wishes,
Grem
> Gregory Marton <INVALID.NOREPLY@gnu.org> writes:
>
>> As an enhancement request, it would be nice for the common case to be able to
>> pass a hash-function argument and assoc to make-hash-table or to have a
>> (make-hashx-table hash assoc [size]), and in either case to remember the hash
>> function so that resize works correctly.
>
> Last email on this topic for tonight...!
>
> Note that anyone wanting to implement this "saner" interface can
> straightforwardly do so in Scheme:
>
> (define hash-table-hash-fn (make-object-property))
>
> (define hash-table-assoc-fn (make-object-property))
>
> (define (make-hashx-table hash assoc . args)
> (let ((t (apply make-hash-table args)))
> (set! (hash-table-hash-fn t) hash)
> (set! (hash-table-assoc-fn t) assoc)
> t))
>
> (define (hashx-table-ref t key)
> (hashx-ref (hash-table-hash-fn t) (hash-table-assoc-fn t) t key))
>
> etc.
>
> Regards,
> Neil
>
>
>
>
>
--
------ __@ Gregory A. Marton http://csail.mit.edu/~gremio/
--- _`\<,_ .
-- (*)/ (*) Truth, Beauty, Love, and Darwinfish!
~~~~~~~~~~~~~~~~-~~~~~~~~_~~~_~~~~~v~~~~^^^^~~~~~--~~~~~~~~~~~~~~~++~~~~~~~
^ permalink raw reply [flat|nested] 13+ messages in thread
* [bug #22022] hashx-set! and -ref
2008-01-17 22:45 ` Neil Jerram
2008-01-18 0:22 ` Gregory Marton
@ 2008-01-29 22:28 ` Neil Jerram
2008-12-07 16:51 ` Neil Jerram
1 sibling, 1 reply; 13+ messages in thread
From: Neil Jerram @ 2008-01-29 22:28 UTC (permalink / raw)
To: Neil Jerram, Gregory Marton, bug-guile
Update of bug #22022 (project guile):
Status: None => Fixed
Open/Closed: Open => Closed
_______________________________________________________
Follow-up Comment #4:
(For the bug record... The following has already been discussed on-list, but
I don't know how to prevent savannah from CC'ing this to bug-guile.) Have
committed (on 2008-01-18) a test and fix for the segfault. Other failed test
have been agreed to be invalid, as discussed below. Will commit other,
passing tests from Gregory Marton once copyright papers are in place.
_______________________________________________________
Reply to this item at:
<http://savannah.gnu.org/bugs/?22022>
_______________________________________________
Message sent via/by Savannah
http://savannah.gnu.org/
^ permalink raw reply [flat|nested] 13+ messages in thread
* [bug #22022] hashx-set! and -ref
2008-01-29 22:28 ` Neil Jerram
@ 2008-12-07 16:51 ` Neil Jerram
0 siblings, 0 replies; 13+ messages in thread
From: Neil Jerram @ 2008-12-07 16:51 UTC (permalink / raw)
To: Neil Jerram, Gregory Marton, bug-guile
Follow-up Comment #5, bug #22022 (project guile):
Grem's copyright assignment has now been processed, so his additional
hashtable tests have been committed.
_______________________________________________________
Reply to this item at:
<http://savannah.gnu.org/bugs/?22022>
_______________________________________________
Message sent via/by Savannah
http://savannah.gnu.org/
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2008-12-07 16:51 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-01-14 22:40 [bug #22022] hashx-set! and -ref Gregory Marton
2008-01-17 21:52 ` Neil Jerram
2008-01-17 21:54 ` Gregory Marton
2008-01-17 23:02 ` Neil Jerram
2008-01-18 0:25 ` Gregory Marton
2008-01-17 21:57 ` Neil Jerram
2008-01-17 22:01 ` Gregory Marton
2008-01-17 22:45 ` Neil Jerram
2008-01-18 0:22 ` Gregory Marton
2008-01-29 22:28 ` Neil Jerram
2008-12-07 16:51 ` Neil Jerram
2008-01-17 23:13 ` Neil Jerram
2008-01-18 0:30 ` Gregory Marton
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).