RFC: hash table pattern matching

Ironically, I think what you just mentioned supports my argument for expressions in key positions. If we have patterns in key positions, the key-comparison mode is probably going to be all wrong.

Consider:

(define x (list 42))
(define y (list 42))
(match (hasheq x 1)
  [(hash* [(== y) v]) v]
  [_ 'no-match])

What should this program evaluate to? If I read the doc of ==, I might think that the answer is 1. But a matching that actually returns 1 would be inefficient because now it needs to search the entire hash table for a key that is equal? to y.

In my proposal, guaranteeing efficient lookup is a design principle. I am matching a hasheq, so I want the key-comparison mode to be eq?, so that I can quickly hash-ref on y. In my proposal:

(define x (list 42))
(define y (list 42))
(match (hasheq x 1)
  [(hash* [y v]) v]
  [_ 'no-match])

would result in 'no-match

Indeed, the current hash-table pattern is similarly “wrong”:

(define x (list 42))
(define y (list 42))
(match (hasheq x 1)
  [(hash-table [(== y) v] [_ _]) v]
  [_ 'no-match])

evaluates to 1, instead of 'no-match.

To reiterate, I think using == and literal patterns is not a good idea. They already have their semantics, which are to use equal? for comparison (by default). But what we want for efficient matching on a hash table is to hash-ref on keys quickly, mandating that we use whatever key-comparison mode that the matching hash table has. Expressions in key positions allow us to do this.

1 Like