guicho271828 / trivia

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

Binding type/predicate pattern #103

Open mister-walter opened 5 years ago

mister-walter commented 5 years ago

I apologize if this isn't the right place to post this question!

I'm looking for a type predicate subpattern that also binds the value it's run on.

My use case is something like this: I want to only match lists that start with a string (or more generally, their first element satisfies some predicate) and also bind the first element of the list.

For simple patterns, something like this works:

(let ((x '("hello" 1))
  (match x
    ((list (type string) y) (cons (foo (car x)) (bar y))))

but ideally I'd like to not have to manually do the (car x).

mister-walter commented 5 years ago

Oops, after fumbling around a bit more with defpattern and guard I managed to get something working:

(defpattern type-bind (ty var)
            (let ((it (gensym "WHATBIND")))
              `(guard1 (,it :type ,ty) t
                       ,it (guard1 ,var t))))

Not sure if this is the best way to do it but it seems to work with my use case!

guicho271828 commented 5 years ago

oh yes, nice idea. Why I did not think about this? Indeed I often write code as below very often; The current type pattern should be extended to support the syntax of your type-bind pattern. Probably the var argument should be &optional.

Appreciated if you try to extend the definition of type pattern.

(match s
  ((list (and x (type string)) y) ... ))

;; proposed:
(match s
  ((list (type string x) y) ... ))
mister-walter commented 5 years ago

Oh wow, I didn't realize you could use and for this!

I'll work on a PR to extend the type pattern definition as you describe it, and I'll also maybe add an example to the wiki showing that usage of and. I probably won't have time until next week, but I'll keep it on my todo list!