| Piggy-backing on the excellent work of almkglor, it is possible to make a generalized case statement that utilizes pattern matching. (require "lib/defpat.arc")
(let trans
(p-m:afn
(()) '()
((x)) `(,x)
((x y . ys))
(let a (if (isa x 'sym) `',x x)
`((,a) ,y ,@(self ys))))
(mac pcase (var . cases)
`((p-m:fn ,@(trans cases)) ,var)))
This behaves in the expected way for any typical use of case. For instance, case and pcase are interchangeable in this definition of translate: (def translate (sym)
(pcase sym
apple 'mela
onion 'cipolla
'che?))
On the other hand, consider the following way to merge two sorted lists: (def union (< xs ys)
(pcase `(,xs ,ys)
(xs ()) xs
(() ys) ys
((x . xt) (y . yt))
(if (< x y) (cons x (union < xt ys))
(< y x) (cons y (union < xs yt))
(cons x (union < xt yt)))))
This cannot be done straightforwardly with defpat / p-m:def because there is no equivalent to "xs@(x:xt)". With pcase, you can match over arbitrary bound variables. The construct (p-m:fn ... ) is roughly equivalent to (fn args (pcase args ... )), where the latter is preferred if you want to bind args. |