Thinking about list pattern matching, there are a few forms that Roc could support:
[1, 2, 3]. Matching an empty list falls under this too.[1, 2, ..] (here .. is a "spread syntax" to mean "there may be be 0 or more elements following the two that I'd like to match, but they are irrelevant to me")[.., 1, 2][1, 2, .., 99, 100][..]Roc compiles pattern matches via decision trees, so all of these could be compiled optimally. In my mind all of these are worth supporting, and can be supported - but is there any reason any of them shouldn't be? And, is the spread syntax .. the right choice, or does it need to be something else for a particular reason?
I assume any of these number literals could also be:
_)yeah?
Yep. That should be natural to extend, those forms are already covered by the decision tree compiler.
Yeah, all of those look great. Can't think of any cases that would make one a mistake to support.
Will be amazing when pattern matching like this can get the length once and then load all elements. No need for many repeated out of bounds checks.
Do you think we could capture the "rest" of the list into another list? Like JavaScript below, but also Elm, Haskell, etc.
const [first, ...others] = [1, 2, 3];
console.log(others); // [2, 3]
Although I guess I use this a lot more in Elm or Haskell for recursion on a linked list. I'm not sure if that makes it a bad idea for Roc! JS has it but I rarely use it I think :thinking:
Anyway I think this feature would be great to have and all the proposed forms make sense!
Probably best to hold off on the "rest" syntax until a compelling use case comes up.
we can mirror rust here with allowing [first, .. as rest]. The performance of that is not great right now though
Should be fine when one day we have seamless slices.
seamless slices should make that fast though I think
A missed case which may be useful:
Match a list containing one or more elements: [.., 4, 5, 6, ..]
It certainly wouldn't be as efficient as head/tail matching, but it is a need that would commonly enough arise (particularly for the single-element case), and if the above were not permitted, programmers would still implement this one their own, albeit less readably.
A related need would be some way to express an order-independent contains across multiple elements: [.., 4, ..] & [.., 5, ..] (this could match [3, 4, 5, 6] as well as [6, 5, 4, 3], among others). I believe it'd be possible to do this in linear time as this seems equivalent to an anywhere-in-string match of the regex 4.*5|5.*4, and there are guaranteed linear-time, memory-bounded regular expression algorithms available.
This seems like a different class of pattern matching. All of these would have a larger cost than the above listed function. I think they probably make more sense as separate functions rather than pattern matching. Otherwise a user might unknowingly greatly increase the cost of pattern matching.
Certainly true
The nice thing about pattern matching is that it is generally linear-cost in nature, so you know roughly how much compute it will take. With arbitrary subcollection searches we would have to lose that
List pattern matching has landed on latest main - support for binding the rest of a list isn’t yet supported, and should probably remain an anti pattern until we properly support slices. But it’s there!
Ayaz Hafiz has marked this topic as resolved.
Last updated: Jun 16 2026 at 16:19 UTC