如何将标识符绑定到子列表加分隔符?

问题描述 投票:0回答:1

这个

match
将标识符
a
b
绑定到列表的前缀
'(0 1)
和后缀
'(3 4 5)

(match '(0 1 2 3 4 5)
  [`(,a ... 2 ,b ...)
   (values a b)])

另一个等价版本:

(match '(0 1 2 3 4 5)
  [`(,@(list a ... 2) ,b ...)
   (values a b)])

如何将标识符(在模式本身内)绑定到前缀

'(0 1 2)
,包括定界符?

pattern-matching match racket sublist
1个回答
0
投票

app
模式,它调用一个具有匹配值的函数,然后匹配它返回的值,结合
splitf-at
的版本,在第一个列表而不是第二个列表中包含分区元素,可以是曾经这样做:

; Like splitf-at but includes the element to split at in the first value not the second
(define (splitf-at/inclusive lst pred?)
  (let loop ([lst lst]
             [first-res '()])
    (cond
      ((empty? lst)
       (values (reverse first-res) '()))
      ((pred? (car lst))
       (loop (cdr lst) (cons (car lst) first-res)))
      (else
       (values (reverse (cons (car lst) first-res)) (cdr lst))))))

; Gives '(0 1 2) '(3 4 5)
(match '(0 1 2 3 4 5)
  ((? list? (app (lambda (lst) (splitf-at/inclusive lst (negate (curry = 2)))) a b))
   (values a b)))

(注意使用

(? list? ...)
来确保值是一个列表,然后再尝试调用任何依赖于它的函数。)

你可以定义一个match extender让它看起来更漂亮:

(define-match-expander split-list
  (lambda (stx)
    (syntax-case stx (...)
      ((_ x (... ...) val y (... ...))
       #'(? list? (app (lambda (lst) (splitf-at/inclusive lst (lambda (elem) (not (equal? elem val))))) x y))))))

; Also gives '(0 1 2) '(3 4 5)
(match '(0 1 2 3 4 5)
  ((split-list a ... 2 b ...)
   (values a b)))
© www.soinside.com 2019 - 2024. All rights reserved.