Abstraction of a racket match
I have several functions that correspond to strings that look like this:
(define (get-bounding-y struct-lst)
(flatten (for/list ([i struct-lst])
(match i
[(line _ _ _ _ _ y1 _ y2) (list y1 y2)]
[(arc _ _ _ _ _ y radius _ _ _ _ _ _ _ _) (list (+ y radius) (- y radius))]
[(point _ _ _ _ _ y) (list y)]
[(path _ _ _ _ path-list) (get-bounding-y path-list)]))))
I would like to divert this so that the structure function
(matcher (return value struct-name1) (return value struct-name2) ...)
i.e. (match (string (+ 1 x1)) (arc radius) (point x) (path objects)) will return this:
(match a-struct
[(struct* line ([x1 x1])) (+ 1 x1)]
[(struct* arc ([radius radius])) radius]
[(struct* point ([x x])) x]
[(struct* path ([entities entities])) entities])
Is it possible?
source to share
You can expand match
. Custom templates are defined using define-match-expander
.
Let's say you have a structure
(struct line (x1 y1 x2 y2))
and you noticed that you are using the match pattern
(line _ y1 _ y2)
again and again. Do you prefer to write
(line* y1 y2)
By using define-match-expander
, you can turn (line* y1 y2)
into (line _ y1 _ y2)
.
Here's a complete example:
(define-match-expander line*
(lambda (stx)
(syntax-case stx ()
[(_line* y1 y2)
#'(line _ y1 _ y2)])))
(match (line 0 1 2 3)
[(line* y1 y2) (list y1 y2)])
Output:
'(1 3)
source to share
This is what I wanted to do, but at the moment it is too specific:
1) it should always contain 4 dots, line, arc, path syntax, even if I only want to match 2 structures
2) the macro is defined in one file, and if I wanted to use functions defined in another file inside the syntax a, b, c, d, it will give me an "unbound identifier in module" error. What I want is a mixture of both the ability to integrate local functions and pull out variables from the left side of the match, but I haven't figured out how to do this yet.
(define-syntax match-struct
(lambda (stx)
(syntax-case stx ()
[(_ (dot a) (line b) (arc c) (path d))
(with-syntax ([tmp0 (syntax->datum #'a)]
[tmp1 (syntax->datum #'b)]
[tmp2 (syntax->datum #'c)])
#'(lambda (a-struct)
(match a-struct
[(dot highlighted selected visible layer p) tmp0]
[(line highlighted selected visible layer p1 p2) tmp1]
[(arc highlighted selected visible layer center radius start end p1 p2 p3) tmp2]
[(path highlighted selected visible layer entities) (d entities)])))])))
source to share