Pattern matching k or more items

Given a pattern like

(match '(1 2 3 4)
[(list 1 a ..3) a]
[_ 'else])

in the above must the ..k form be a literal non-negative integer? Can k not be an identifier bound to a non-negative identifier?

Hi, @jeh.

As far as I know, you can't do what you're asking out of the box, but if you're willing to mess around with some match-expanders, you could probably mock-up what you're looking for:

#lang racket/base

(require
  racket/match
  (for-syntax
   racket/base
   racket/syntax))

(define-for-syntax (make-slice n)
  (datum->syntax #false (string->symbol (format "..~a" (syntax-e n)))))

(define-match-expander slice
  (lambda (stx)
    (syntax-case stx ()
      [(_ id count) #``(,id #,(make-slice #'count))])))

(match '(1 2 3 4)
  [`(,@(slice a 3) ,rest ..1)
   (list a rest)]
  
  [_ #false])

;=> '((1 2 3) (4))

For what it's worth, there are a couple of patterns which seem like they should be doable with normal matches, but aren't at present, mostly related to splicing-patterns.

I hope that helps.

You can also use #:when

(match (list 1 2 3 4)
  [(list 1 as ...)
   #:when (>= (length as) n)
   as]
  [_ 'else])
1 Like

... must the ..k form be a literal non-negative integer?
Yes.