2015-01-16 50 views
0

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

不幸的是,這種失敗,因爲ab,和c,是綁定在函數傳遞給app模式被調用。有什麼辦法來實現這樣的匹配擴展器,以便它可以對匹配的值執行一些任意的過程?

回答

1

是,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") 
1

首先,在你的pregexp模式的錯字:

(pregexp #px"^(.+)\\s(.+)\\s(.+)$" a b c) 

我想你想:

(pregexp #px"^(.+)\\s(.+)\\s(.+)$" (list _ a b c)) 

至於你的主要目標:

我經常發現自己匹配在其他模式中的三個元素的列表,然後從它創建一個結構。因此,我想簡化這一點....

那麼,你可以通過使用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)])))