在Racket Scheme中的"匹配"表格.关于匹配序列的问题

tkf*_*tkf 2 scheme racket

我正在尝试使用Racket的"匹配"表单,并希望匹配列表中的项目序列.每个项目都有特定的属性.例如,如果我想匹配交替的数字和字符串序列(大致)与正则表达式匹配:

#rx"([0-9]+ \"[a-zA-Z0-9]+\")+"
Run Code Online (Sandbox Code Playgroud)

下面的代码似乎可以完成这项工作:

(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)))
Run Code Online (Sandbox Code Playgroud)

我意识到上面的#rx和代码并不完全匹配相同的序列,但它只是一个类比.

这是在Racket中写这个最简洁的方式吗?

我试过像这样的模式:

(list ((? number? n) (? string? s)) ...)
Run Code Online (Sandbox Code Playgroud)

而且球拍不接受这个.

模式如:( list(?number?n)(?string?s)...)要求匹配的列表的第一项是数字,其他所有项都是字符串.

我尝试了几种方式的quasiquotation和拼接,没有成功.

必须有一个更优雅的阵型,但我似乎无法找到它.任何帮助,将不胜感激.谢谢.

Eli*_*lay 5

看起来像你试图从休息,这并不难分离的数字:

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

但在这种情况下,您可以使用filter,甚至更好partition:

(partition number? '(1 "a" "b" 2 3 "c" "d" 4))
Run Code Online (Sandbox Code Playgroud)

但也许你想把字符串子序列组合在一起,上面的代码更接近:

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

在这种情况下,使用多个值而不是组成列表包装器更容易:

(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 '() '())]))
Run Code Online (Sandbox Code Playgroud)