Do hash-key and hash-values give their results in the same order?

When working with hash tables in Racket, two useful functions are hash-keys and hash-values. The first returns all the keys used in the hash table, as a list. The second returns, analogously, the values. Nothing terribly surprising there.

When we need to work, separately, with the keys and the values of a hash table, an interesting question presents itself:

Is it safe to assume that the list that hash-keys returns has the same order as the list returned by hash-values?

Is, for instance, the first element of the list returned by hash-values the hash value of the first element returned by hash-keys? To put the question in terms of code: is it true, for a hash table h, that

(equal? (list-ref (hash-values h) 0)
        (hash-ref h (list-ref (hash-keys h) 0)))

and so forth, for 1, 2, etc.?

The answer is: No, that is not necessarily true.

If, in some cases, it is true, that’s accidental and not something to rely upon. The documentation for both functions says that the results are provided in an unspecified order.

Think of it this way. When using hash-keys and hash-values, you’re losing information. Applying these functions deliberately cuts the tie between the key and values of a hash. hash-key gives just a list of keys; it makes no promises about the order of its results. And similarly for hash-values.

Demonstration

Here’s how you can convince yourself of this. Run the following code in DrRacket:

#lang racket

(define h (make-hash '(("a" . 0) ("b" . -1) ("c" . 4))))

(hash-keys h)
;; ("c" "a" "b")

(hash-values h)
;; (-1 0 4), 'wrong' order

These results show that you can’t really rely on the order. If you get results that don’t contradict the conjecture, consider yourself lucky.