Stream: ideas

Topic: ✔ list pattern matching


view this post on Zulip Ayaz Hafiz (Oct 25 2022 at 03:03):

Thinking about list pattern matching, there are a few forms that Roc could support:

  1. Match a list exactly: [1, 2, 3]. Matching an empty list falls under this too.
  2. Match the head of a list, with at least N elements: [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")
  3. Match the tail of a list, with at least N elements: [.., 1, 2]
  4. Math both the head and tail of a list: [1, 2, .., 99, 100]
  5. Match a non-empty list, disregarding binding any elements to a variable, or matching them with a literal: [..]

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?

view this post on Zulip Richard Feldman (Oct 25 2022 at 03:07):

I assume any of these number literals could also be:

yeah?

view this post on Zulip Ayaz Hafiz (Oct 25 2022 at 03:17):

Yep. That should be natural to extend, those forms are already covered by the decision tree compiler.

view this post on Zulip Brendan Hansknecht (Oct 25 2022 at 04:03):

Yeah, all of those look great. Can't think of any cases that would make one a mistake to support.

view this post on Zulip Brendan Hansknecht (Oct 25 2022 at 04:07):

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.

view this post on Zulip Brian Carroll (Oct 25 2022 at 06:22):

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]

view this post on Zulip Brian Carroll (Oct 25 2022 at 06:27):

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:

view this post on Zulip Brian Carroll (Oct 25 2022 at 06:32):

Anyway I think this feature would be great to have and all the proposed forms make sense!

view this post on Zulip Brian Carroll (Oct 25 2022 at 06:32):

Probably best to hold off on the "rest" syntax until a compelling use case comes up.

view this post on Zulip Folkert de Vries (Oct 25 2022 at 07:22):

we can mirror rust here with allowing [first, .. as rest]. The performance of that is not great right now though

view this post on Zulip Brendan Hansknecht (Oct 25 2022 at 14:03):

Should be fine when one day we have seamless slices.

view this post on Zulip Richard Feldman (Oct 25 2022 at 18:18):

seamless slices should make that fast though I think

view this post on Zulip Kevin Gillette (Oct 26 2022 at 06:08):

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.

view this post on Zulip Brendan Hansknecht (Oct 26 2022 at 06:12):

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.

view this post on Zulip Kevin Gillette (Oct 26 2022 at 06:40):

Certainly true

view this post on Zulip Ayaz Hafiz (Oct 26 2022 at 12:30):

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

view this post on Zulip Ayaz Hafiz (Nov 02 2022 at 02:33):

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!

view this post on Zulip Notification Bot (Nov 02 2022 at 02:33):

Ayaz Hafiz has marked this topic as resolved.


Last updated: Jun 16 2026 at 16:19 UTC