guicho271828 / trivia

Pattern Matcher Compatible with Optima
Other
332 stars 22 forks source link

A hashmap pattern #88

Closed libre-man closed 3 years ago

libre-man commented 6 years ago

As hash maps have really nice performance characteristics I use them quite a lot in my code. The support for hashmaps in trivia is not perfect, as I can't bind them in the pattern nor can I bind specific items of the hashmap by default. I have a pattern that can do both those things and I was wondering if you would be open to a PR containing such a pattern.

ghost commented 6 years ago

It'd be useful if you could provide a code fragment illustrating the use case.

libre-man commented 6 years ago

Something like this is really useful as decreases the amount of nesting needed:

(match (function-returning-hashmap)
  ((hash ("val" item) map)
   (do-with-map-and-val item map))
  ((hash (:other-key item) map)
   (do-else-with-map-and-val item map))
  (otherwise (error "Not good!")))
ghost commented 6 years ago

That's definitely useful; I'd prefer that you follow the semantics of the property pattern, though.

(match <plist>
  ((property <key> <binding> <default> <exists-p>) <binding>))

( @guicho271828 has the final say of course.)

guicho271828 commented 6 years ago

@libre-man I am generally open to pull request and even willing to give you write access, thereby you have the responsibility to maintain the part of the code you commited.

Just curious, what do you mean by a hashmap? Do you mean a hash table?

libre-man commented 6 years ago

Sorry I did mean a hash table. I'll create a pull request the following days, thanks!

guicho271828 commented 6 years ago

Thank you for the clarification, since hashmap sounds like C++ map that gives you an ordered map.

dop commented 3 years ago

I've written hash-table pattern for myself.

(defpattern hash-key (key pattern)
  (alexandria:with-gensyms (it)
    `(trivia:guard1 ,it (nth-value 1 (gethash ,key ,it))
                    (gethash ,key ,it) ,pattern)))

(defpattern hash-table (&rest kvs)
  `(and (type hash-table)
        ,@(loop for (key pattern) on kvs by #'cddr
                collect `(hash-key ,key ,pattern))))

To be able to write code like this:

(match (alexandria:alist-hash-table '((:a . 1) (:b . 2) (:c . 3)))
  ((hash-table :a 1 :b x) x)) ;; => 2

Would something like that be useful to include?

guicho271828 commented 3 years ago

I accept it if you submit a request