在球拍中抽象出比赛
abstracting away match in 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)]))))
我想将其抽象化,以便结构的函数
(匹配器(结构名称1 return-值) (结构名称2 return-值) ...)
即(matcher (line (+ 1 x1)) (arc radius) (point x) (path entities))
将 return 这个:
(match a-struct
[(struct* line ([x1 x1])) (+ 1 x1)]
[(struct* arc ([radius radius])) radius]
[(struct* point ([x x])) x]
[(struct* path ([entities entities])) entities])
这可能吗?
您可以扩展 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) 它必须始终是 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)])))])))
我有几个函数匹配这样的结构:
(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)]))))
我想将其抽象化,以便结构的函数
(匹配器(结构名称1 return-值) (结构名称2 return-值) ...)
即(matcher (line (+ 1 x1)) (arc radius) (point x) (path entities)) 将 return 这个:
(match a-struct
[(struct* line ([x1 x1])) (+ 1 x1)]
[(struct* arc ([radius radius])) radius]
[(struct* point ([x x])) x]
[(struct* path ([entities entities])) entities])
这可能吗?
您可以扩展 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) 它必须始终是 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)])))])))