2016-07-25 67 views
5

我經常使用Racket的模式匹配構造match,我想通過使用match來幫助自己調試程序,並且瞭解Racket/Scheme宏是如何工作的,可以創建一個包含像哪種模式匹配的信息。宏定義中的升序編號

換句話說,我期待創造,鑑於此宏:

(match/debug 'two 
    ['one 1] 
    ['two 2]) 

輸出是這樣的:

Case 2 <-- Printed 
2  <-- Returned value 

的主要障礙至今一直試圖讓數字表示解決的案例正確顯示。

我的目標是嘗試寫一些東西,將擴大這樣的:

(match 'two 
    ['one (displayln "Case 1") 1] 
    ['two (displayln "Case 2") 2]) 

但我一直無法找出任何方式產生那些「案例#」字符串。

這是我嘗試宏定義:

(define-syntax-rule (match/debug id [pattern value] ...) 
    (let ([index 0]) 
    (match id 
     [(begin 
     (set! index (add1 index)) 
     pattern) 
     (printf "Case ~a\n" index) 
     value] ...))) 

看來好像的match語法不會讓我做這樣的事情,但是這是我能想到的唯一途徑。我只是非常習慣Common Lisp的宏的風格。

回答

5

這是一個解決方案。

幫助函數clauses->numbers返回一個從0到小於子句數的列表。然後這被用於給每個子句自己的數字。請注意,此解決方案從0開始計數(而不是您的示例中的1)。

#lang racket 
(require (for-syntax syntax/parse)) 

(begin-for-syntax 
    (require racket/list) ; import range 
    (define (clauses->numbers stx) 
    (range (length (syntax->list stx))))) 

(define-syntax (match/debug stx) 
    (syntax-parse stx 
    [(_match/debug id [pattern value] ...) 
    (with-syntax ([(n ...) (clauses->numbers #'([pattern value] ...))]) 
     (syntax/loc stx 
     (match id 
      [pattern (begin (displayln (~a "Case: " n)) value)] 
      ...)))])) 

(match/debug 'one 
    ['one 1] 
    ['two 2]) 

(match/debug 'two 
    ['one 1] 
    ['two 2]) 

輸出:

Case: 0 
1 
Case: 1 
2 
+0

有趣的是......其實我結束了使用引用的模式,它給了我足夠的信息。但是,謝謝你的快速和徹底的迴應! – mellowmaroon