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?

+3


source to share


2 answers


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)

      

+1


source


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)])))])))

      

+1


source







All Articles