如何使用模式匹配的结果在匹配扩展器中生成值?
How can I use the results of a pattern match to produce a value in a match-expander?
在 racket/match
模式中,我想匹配一些值,然后创建一个包装它们的结构。例如,采用以下(设计的)代码:
(struct foo (a b c))
(define (foo-from-string str)
(match str
[(pregexp #px"^(.+)\s(.+)\s(.+)$" (list _ a b c))
(foo a b c)]
[_ #f]))
我经常发现自己在其他模式中匹配这个包含三个元素的列表,然后从中创建一个结构。因此,我想通过编写自定义匹配扩展器来简化这一点。理想情况下,它会像这样工作:
(struct foo (a b c))
(define (foo-from-str str)
(match str
[(foo-string value) value]
[_ #f]))
也就是说,它应该自动匹配满足正则表达式的字符串,然后在成功时将值存储到 foo
结构中并将其绑定到 value
。我尝试编写如下内容来实现此目的:
(define-match-expander foo-string
(λ (stx)
(syntax-case stx ()
[(_ result)
#'(and (pregexp #px"^(.+)\s(.+)\s(.+)$" (list _ a b c))
(app (λ (v) (foo a b c)) result))])))
不幸的是,这失败了,因为 a
、b
和 c
在调用传递给 app
模式的函数时未绑定。有什么方法可以实现这样的匹配扩展器,以便它可以对匹配值执行一些任意过程吗?
首先,您的 pregexp
格式有错字:
(pregexp #px"^(.+)\s(.+)\s(.+)$" a b c)
我想你想要:
(pregexp #px"^(.+)\s(.+)\s(.+)$" (list _ a b c))
至于你的主要目标:
I frequently find myself matching this list of three elements in other patterns, then creating a struct from it. Therefore, I wanted to simplify this....
好吧,您可以通过使用 app
和合适的函数来完成此操作。有趣的是,您的 foo-from-string
函数是...正是那个合适的函数。
例如,要匹配一个字符串并得到一个 foo
结构:
(match "a b c"
[(app foo-from-string x) x])
;;=> (foo "a" "b" "c")
或者要匹配字符串并获取 foo
字段,请提供 foo
结构模式:
(match "a b c"
[(app foo-from-string (foo a b c)) (list a b c)])
;;=> '("a" "b" "c")
诚然,我没有回答您有关匹配扩展器的问题,因为我对它们的了解还不够深入。所以我建议你也许不需要它们?
更新:实际上这似乎也是对匹配扩展器的回答:
(define-match-expander foo-string
(λ (stx)
(syntax-case stx ()
[(_ x)
#'(app foo-from-string x)])))
是的,app
正是您想要的。您只需要在 app
.
中做更多
#lang racket
(struct foo (a b c) #:transparent)
(define-match-expander foo-string
(λ (stx)
(syntax-case stx ()
[(_ result)
#'(app (λ (v) (apply (λ (_ a b c) (foo a b c))
(regexp-match #px"^(.+)\s(.+)\s(.+)$" v)))
result)])))
(define (foo-from-str str)
(match str
[(foo-string value) value]
[_ #f]))
(foo-from-str "1 2 3")
在 racket/match
模式中,我想匹配一些值,然后创建一个包装它们的结构。例如,采用以下(设计的)代码:
(struct foo (a b c))
(define (foo-from-string str)
(match str
[(pregexp #px"^(.+)\s(.+)\s(.+)$" (list _ a b c))
(foo a b c)]
[_ #f]))
我经常发现自己在其他模式中匹配这个包含三个元素的列表,然后从中创建一个结构。因此,我想通过编写自定义匹配扩展器来简化这一点。理想情况下,它会像这样工作:
(struct foo (a b c))
(define (foo-from-str str)
(match str
[(foo-string value) value]
[_ #f]))
也就是说,它应该自动匹配满足正则表达式的字符串,然后在成功时将值存储到 foo
结构中并将其绑定到 value
。我尝试编写如下内容来实现此目的:
(define-match-expander foo-string
(λ (stx)
(syntax-case stx ()
[(_ result)
#'(and (pregexp #px"^(.+)\s(.+)\s(.+)$" (list _ a b c))
(app (λ (v) (foo a b c)) result))])))
不幸的是,这失败了,因为 a
、b
和 c
在调用传递给 app
模式的函数时未绑定。有什么方法可以实现这样的匹配扩展器,以便它可以对匹配值执行一些任意过程吗?
首先,您的 pregexp
格式有错字:
(pregexp #px"^(.+)\s(.+)\s(.+)$" a b c)
我想你想要:
(pregexp #px"^(.+)\s(.+)\s(.+)$" (list _ a b c))
至于你的主要目标:
I frequently find myself matching this list of three elements in other patterns, then creating a struct from it. Therefore, I wanted to simplify this....
好吧,您可以通过使用 app
和合适的函数来完成此操作。有趣的是,您的 foo-from-string
函数是...正是那个合适的函数。
例如,要匹配一个字符串并得到一个 foo
结构:
(match "a b c"
[(app foo-from-string x) x])
;;=> (foo "a" "b" "c")
或者要匹配字符串并获取 foo
字段,请提供 foo
结构模式:
(match "a b c"
[(app foo-from-string (foo a b c)) (list a b c)])
;;=> '("a" "b" "c")
诚然,我没有回答您有关匹配扩展器的问题,因为我对它们的了解还不够深入。所以我建议你也许不需要它们?
更新:实际上这似乎也是对匹配扩展器的回答:
(define-match-expander foo-string
(λ (stx)
(syntax-case stx ()
[(_ x)
#'(app foo-from-string x)])))
是的,app
正是您想要的。您只需要在 app
.
#lang racket
(struct foo (a b c) #:transparent)
(define-match-expander foo-string
(λ (stx)
(syntax-case stx ()
[(_ result)
#'(app (λ (v) (apply (λ (_ a b c) (foo a b c))
(regexp-match #px"^(.+)\s(.+)\s(.+)$" v)))
result)])))
(define (foo-from-str str)
(match str
[(foo-string value) value]
[_ #f]))
(foo-from-str "1 2 3")