RFC: hash table pattern matching

I think list-no-order and hash are equivalent, and I expect a total disjoint match for both. I think it’s very difficult to implement that efficiently (probably np-hard). I’m not sure if it’s the best election for the default implementation, but it’s what my fingers feels is correct.

Indeed, list-no-order and hash-table (the current pattern in 8.7/8.8) are essentially equivalent (if you don’t count the bug that makes hash-table allow partial matching).

But now, we have an opportunity to design a totally new pattern with new semantics. My question is, should list-no-order and the new pattern still be equivalent?

And this bring us back again to the point that I wrote earlier:

I can argue in the opposite direction that, if I know that a pattern can produce inefficient code, without being clear under what condition it produces inefficient code, I might avoid using it altogether out of fear of being inefficient.

match already has this problem. For example, I don’t know how efficient (list x xs … y) is. Optimally it can be done in linear time, but does match do that? I don’t know, so I have been avoiding using it.

Not allowing key positions to be general patterns guarantees efficiency, allowing users to be able to use it without any concern.

And just to repeat what @shhyou said, if you do want the list-no-order semantics, you can still have it by writing (app hash->list (list-no-order XYZ ...)). That “the name is more scary” is a good thing! It warns users that its usage is inefficient, so it must be used with caution. On the other hand, they can use the hash pattern without any worry. It is guaranteed to be efficient.

There are four options (or more). IIUC in your proposal

  • no grouping / partial = (hash ...... #:partial) or (hash ...... #:rest _)
  • grouping / total = (hash* ....... #:full)

Unless you really want to have four patterns, which I think would be cluttering.

For hash-rest, as I wrote above, I think it’s better to not have it because hash{,*,-rest} is not like list{,*,-rest}, and having them could make it appear that they are similar than they should. Though again, we can easily add it if that’s the consensus.

Note that you can already do (hash{,*} ...... #:rest .....) in my proposal.