2015-06-04 3 views
3

У меня есть несколько функций, соответствующие для структур, которые выглядят как такие:абстрагируясь от матча в ракетке

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

Я хотел бы абстрагироваться это далеко, так что функция структуры

(Сличитель (struct-name1 return-value) (struct-name2 return-value) ...)

ie (согласование (строка (+ 1 x1)) (радиус дуги) (точка x) (объекты траектории)) будет вернуть это:

(match a-struct 
     [(struct* line ([x1 x1]))    (+ 1 x1)] 
     [(struct* arc ([radius radius]))  radius] 
     [(struct* point ([x x]))    x] 
     [(struct* path ([entities entities])) entities]) 

Возможно ли это?

+0

Должно быть легко с макросом, но ваши данные, похоже, пропустят некоторые вещи. – leppie

+0

Эй, какие подробности мне не хватает? – KRC

+0

Данную '(строка x1)', где используется 'x1', или, альтернативно, в чем смысл« привязки »' ([x1 x1]) '? Кроме того, вам нужно будет передать 'a-struct' где-нибудь в' matcher'. – leppie

ответ

1

Вы можете расширить match. Пользовательские шаблоны определяются с помощью define-match-expander.

Допустим, у вас есть

-структуру
(struct line (x1 y1 x2 y2)) 

и вы наблюдаете вы используете шаблон матча

(line _ y1 _ y2) 

снова и снова. Вы предпочитаете писать

(line* y1 y2) 

Использование define-match-expander вы можете превратить (line* y1 y2) в (line _ y1 _ y2).

Вот полный пример:

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

Выход:

'(1 3) 
1

Это было то, что я хотел сделать, но на данный момент это слишком специфичны:

1) он должен всегда содержать 4 точки, линию, дугу, синтаксис пути, даже если я хочу только совместить 2 структуры

2) макрос определен в одном файле, и если бы я хотел использовать функции, определенные в другом файле внутри синтаксиса a, b, c, d, он даст мне ошибку «unbound identifier in module». То, что я хочу, представляет собой смесь как способности интегрировать локальные функции, так и вытаскивать переменные с левой стороны матча, но я еще не понял, как это сделать.

(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)])))]))) 
Смежные вопросы