I am experimenting with Racket's 'match' form and would like to match sequences of items in a list. Each item will have particular properties. For example, if I wanted to match alternating sequences of numbers and strings corresponding (roughly) to the regular expression:
#rx"([0-9]+ \"[a-zA-Z0-9]+\")+"
The code below seems to do the job:
(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)))
I realize that the #rx and code above don't quite match the same sequences but it is just an analogy.
Is this the most succinct way of writing this in Racket?
I tried patterns like:
(list ((? number? n) (? string? s)) ...)
and Racket did not accept this.
Patterns like: (list (? number? n) (? string? s) ...) require the first item of the list being matched to be numeric and all others to be strings.
I tried quasiquotation and splicing in several ways with no success.
There must be a more elegant formation but I can't seem to find it. Any help would be appreciated. Thanks.