💾 Archived View for idiomdrottning.org › matchable-custom-destructuring captured on 2023-11-14 at 08:26:20. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2023-03-20)
-=-=-=-=-=-=-
Easily the two features I use the most in Matchable (which I mostly use through my match generics) are ? and =, the custom predicate and the custom accessor respectively.
(Those match generics, probably better known as the fanciest define of all time.)
I’ve found that the ?-> combinator is a great match for = when you conditionally want to coerce a data type into another type.
Another comfy use for = is with a custom destructurer that you can then further destructure with matchable. You can just keep on nesting = procs deep in there at every layer.
Here’s a simple example.
This is from the SVG path lib from earlier today. The context is a procure named distance that takes two attribute alists, like ((coords (x n) (y n))), and calculates the Pythagorean diagonal distance between them.
Here is the custom destructurer, which in turn uses alist-ref in its own destructuring parameter list to grab ((x n) (y n)) and then returns a list of those just two numbers.
(define (get-coords (= (c alist-ref 'coords) atts)) (list (car (alist-ref 'x atts)) (car (alist-ref 'y atts))))
And here’s how that destructurer is used in practice, twice, in order to bind the values in those lists directly.
(define (distance (= get-coords (x1 y1)) (= get-coords (x2 y2))) (hypothenuse (- x1 x2) (- y1 y2)))
Using = first and then furthering destructuring the value with another pattern might not have been intended (since it was created primarily for record access) but it’s so flexible and it, along with ?, is an easy way for end users to extend Matchable.
Matchable is awesome and I'm so grateful to Andrew Wright and Alex Shinn for putting it together.
?-> A conditionally transforming combinator
An SVG path data library for Chicken Scheme
Here is another example of how severly brev’s defines can destructure thanks to matchable:
(define (gemline->entry (and gemline (= string-split (_ (= urlfix (and url (= url->string page))) date . _)))) ...body that uses gemline, url, date, and page...)
This is a procedure that takes a string as input, a gmisub-style link line (line type, url, date, and title). Urlfix encodes punycode links while url->string fetches the full text located by an URL.
The and-wrapping lets you use both the whole and the destructured version. (Haskell nerds are familiar with this.) You don’t need it when you only need the destructured version, like how I only need the urlfixed version of the URL.
But I do need both the gemline as a whole along with the url and date, and I do need both the url and the page, hence the ands there.