2016-07-25 7 views
5

Ich benutze häufig Rackets Pattern-Matching-Konstrukt match, und ich dachte mir einen Weg, um Debuggen von Programmen mit match, und um zu lernen, wie Racket/Scheme-Makros zu arbeiten, wäre ein Makro zu erstellen Informationen darüber, welches Muster gefunden wurde.Aufsteigende Zahlen in Makrodefinition

Mit anderen Worten, ich suche ein Makro, das, diese gegeben zu erstellen:

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

Ausgänge etwas wie folgt aus:

Das Haupthindernis weit
Case 2 <-- Printed 
2  <-- Returned value 

so versucht hat, zu erhalten die Zahlen bedeuten, dass der aufgelöste Fall korrekt angezeigt wird.

Mein Ziel war es, zu versuchen, etwas zu schreiben, die wie folgt erweitern würde:

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

Aber ich habe nicht in der Lage gewesen, eine Art und Weise, um herauszufinden, diese „Case #“ Strings zu erzeugen.

Hier ist meine versucht Makrodefinition:

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

Es scheint, als ob die Syntax von match wird mir so etwas wie dies nicht zulassen, aber das war der einzige Weg, ich denken konnte. Ich bin nur an den Stil von Common Lisp gewöhnt.

Antwort

5

Hier ist eine Lösung.

Die Hilfsfunktion clauses->numbers gibt eine Liste der Zahlen von 0 bis zur Zahl kleiner als die Anzahl der Klauseln zurück. Dies wird dann verwendet, um jeder Klausel eine eigene Nummer zu geben. Beachten Sie, dass diese Lösung von 0 (und nicht 1 wie in Ihren Beispielen) zählt.

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

Der Ausgang:

Case: 0 
1 
Case: 1 
2 
+0

Funnily genug ... Ich landete tatsächlich auf die zitierte Muster verwenden, es gab mir genügend Informationen. Aber danke für die schnelle und gründliche Antwort! – mellowmaroon