在球拍中抽象出比赛

时间:2015-06-04 08:02:34

标签: racket

我有几个匹配结构的函数,如下所示:

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

我想把它抽象出去,以便结构的功能

(matcher(struct-name1 return-value)(struct-name2 return-value)...)

即。 (匹配器(行(+ 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])

这可能吗?

2 个答案:

答案 0 :(得分: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)

这就是我想要做的,但目前它太具体了:

1)即使我只想匹配2个结构,它也必须始终是4点,线,弧,路径语法

2)宏在一个文件中定义,如果我想使用语法a,b,c,d中的另一个文件中定义的函数,它将给出一个错误“模块中的未绑定标识符”。我想要的是既能整合局部功能又能从比赛左侧拉出变量的能力,但我还没想出怎么做。

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