Форма «матч» в Схеме Ракетки.Вопрос о сопоставлении последовательностей - PullRequest
2 голосов
/ 15 августа 2011

Я экспериментирую с формой 'соответствия' Ракета и хотел бы сопоставить последовательности элементов в списке. Каждый предмет будет иметь определенные свойства. Например, если я хотел сопоставить чередующиеся последовательности чисел и строк, соответствующие (примерно) регулярному выражению:

#rx"([0-9]+ \"[a-zA-Z0-9]+\")+"

Код ниже, кажется, делает работу:

(define (match-sequence L)
  (let ([n-lst '()]     ; Used to collect numbers found.
        [s-lst '()])    ; Used to collect strings found.
    (define  (m-test L)
      (match L
             [(list-rest (? number? n) (? string? s)  ... (? m-test))
              (set! n-lst `(,@n-lst ,n))
              (set! s-lst `(,@s-lst ,(car s)))                
              (list (reverse n-lst) (reverse s-lst))]
             ['()
              #t]
             [else
             #f]))
    (m-test L)))

Я понимаю, что #rx и код выше не совсем совпадают с последовательностями, но это просто аналогия.

Это самый лаконичный способ написать это в Ракетке?

Я пробовал шаблоны как:

(list ((? number? n) (? string? s)) ...)

и Ракет не принял это.

Шаблоны типа: (список (? number? n) (? string? s) ...) требует, чтобы первый элемент списка соответствовал числовому, а все остальные - строкам.

Я пробовал квазиквотацию и сращивание несколькими способами, но безуспешно.

Должно быть, есть более элегантное образование, но я не могу его найти. Любая помощь будет оценена. Спасибо.

1 Ответ

5 голосов
/ 15 августа 2011

Это выглядит , как будто вы пытаетесь отделить числа от остальных, что не так сложно:

(define (match-sequence L)
  (match L
    [(list* (? number? n) (? string? s) ... rest)
     (let ([r (match-sequence rest)])
       (list `(,n ,@(car r)) `(,@s ,@(cadr r))))]
    ['() '(() ())]))

, но в этом случае вы можете просто использовать filter, или даже лучше, partition:

(partition number? '(1 "a" "b" 2 3 "c" "d" 4))

Но, возможно, вы хотите сгруппировать строковые подпоследовательности, где приведенный выше код ближе:

(define (match-sequence L)
  (match L
    [(list* (? number? n) (? string? s) ... rest)
     (let ([r (match-sequence rest)])
       (list `(,n ,@(car r)) `(,s ,@(cadr r))))]
    ['() '(() ())]))

и в этом случае проще использовать несколько значений вместо составления обертки списка:

(define (match-sequence L)
  (match L
    [(list* (? number? n) (? string? s) ... rest)
     (let-values ([(ns ss) (match-sequence rest)])
       (values `(,n ,@ns) `(,s ,@ss)))]
    ['() (values '() '())]))
...