Arc Forumnew | comments | leaders | submitlogin
Small pattern matching macro
1 point by araujo 6125 days ago | 3 comments
One thing I would like to see in Arc is a good and flexible way of approaching pattern patching.

This is a small test for implementing or give an idea about how pattern matching could work in Arc.

I personally would like something simple either to use as to implement. So I came up with the following:

   (def eqlst (lst1 lst2)
      (if (and (no lst1) (no lst2))
         t
      (and (atom (car lst1)) (atom (car lst2)))
         (if (is (len lst1) (len lst2))
            (eqv (cdr lst1) (cdr lst2))
            nil)
      (and (isa (car lst1) 'cons) (isa (car lst2) 'cons))
         (eqv (cdr lst1) (cdr lst2))
      nil))


   (set defp (annotate 'mac
      (fn (name parms . body)
         `(safeset ,name (fn ,parms
             (let (match p) (list (pair ',body) ,@parms)
                (let found (find [eqlst (car _) ,@parms] match)
                   (eval `(let ,(car found) ',p ,(cadr found))))))))))
The function would work like:

   (defp sum^mul (arg)
         ((z y) x) (+ (* z y) x)
         (z y) (+ z y)
         (z) (* z z))
Which gives the different pattern variations for sum^mul:

   (sum^mul '((126 9) 90)) => 1224
   (sum^mul '(7 134)) => 141
   (sum^mul '(13)) => 169
Notice how it returns nil in case none pattern is properly matched , which I think it is a good way of handling such a situation so we could get at the same time a nice pattern-finder function:

   (find [sum^mul _] '((13 (89)) ((34)) (45 7)))
Though I don't claim this is the best approach for implementing it ; I do think it is a very nice semantic for such an operation , and it is what this code snippet mainly try to show here.

Comments?



3 points by almkglor 6124 days ago | link

http://git.nex-3.com/arc-wiki.git?a=blob;f=lib/defpat.arc;h=... http://arclanguage.org/item?id=2556 http://arclanguage.org/item?id=2276 http://arclanguage.org/item?id=1825

-----

1 point by bogomipz 6124 days ago | link

What happens to arg in (defp sum^mul (arg) ... ) ?

Wouldn't it be better if the function was to be called like this?

  (sum^mul '(126 9) 90) => 1224
  (sum^mul 7 134) => 141
  (sum^mul 13) => 169

-----

1 point by araujo 6124 days ago | link

I really had thought of getting something apparently cleaner , like the syntax you are proposing. At the end I decided it'd be better to preserve an 'argument' field to clearly indicate that it is a function-like definition and we need to pass an argument to it , something more like a spec:

   (sig 'sum^mul) => (arg)
Besides being a good visual indicator, it also plays a role inside the macro definition , this is the variable containing the value to be matched against the different patterns internally, so in this case, such a variable is actually needed too.

Pattern-matching operates over 'data structures' , that is why we need to pass lists (or another structure) to the function. I think there is no need to increase complexity on this, or probably creates confusion about it.

-----