2016-07-25 16 views
5

Często stosuję konstrukcję dopasowywania wzorców Racket'a match, i pomyślałem, że mogę pomóc sobie przy debugowaniu programów przy użyciu match, i aby dowiedzieć się, jak działają makra Racket/Scheme, należy utworzyć makro, które zawiera informacje takie, jaki wzorzec został dopasowany.Rosnące numery w definicji makra

Innymi słowy, szukam, aby utworzyć makro, które, biorąc pod uwagę to:

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

Wyjścia coś takiego:

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

Główną przeszkodą do tej pory stara się dostać liczby oznaczające, że rozwiązany przypadek wyświetla się poprawnie.

Moim celem było, aby spróbować napisać coś, co mogłoby rozwinąć tak:

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

Ale nie byłem w stanie wymyślić jakiś sposób, aby wygenerować te „Case #” sznurki.

Oto moja próba definicja makra:

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

Wydaje się jakby składni match nie pozwoli mi zrobić coś takiego, ale to był jedyny sposób mogę myśleć. Jestem bardzo przyzwyczajony do makr Common Lisp.

Odpowiedz

5

Oto rozwiązanie.

Funkcja pomocnika clauses->numbers zwraca listę liczb od 0 do mniejszej niż liczba klauzul. Następnie używa się tego, aby nadać każdej klauzuli swój własny numer. Zauważ, że to rozwiązanie liczy się od 0 (a nie 1, jak w przykładach).

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

Wyjście:

Case: 0 
1 
Case: 1 
2 
+0

Zabawne ... I rzeczywiście skończyło się używając cytowany wzór, to dał mi wystarczająco dużo informacji. Ale dzięki za szybką i dokładną odpowiedź! – mellowmaroon