This is a thing from Elixir that I definitely miss in other languages that don't have it. Extremely useful when chewing through binary data of any kind.
(To see examples of it in Elixir, see: https://elixir.hexdocs.pm/binaries-strings-and-charlists.html )
I think this already works with list patterns, right?
[1, 2, 3, ..] =>
Elixir and Gleam has some more pattern syntaxes, but I don't know whether it would be a good idea to add them to Roc.
I think one difference is that Elixir allows you to pattern match on lengths too:
<<head::binary-size(2), rest::binary>> = <<0, 1, 2, 3>> extracts 0 and 1, so for instance if you wanted to chunk out some headers of known size, followed by the rest.
I don't find it as readable, but it might be because I'm not used to it.
Maybe a list matching pattern that matches an n length sublist of a List, not just one item?
Yes it tripped me up a few times because it feels like quite special cased syntax
Also, big vs little endian is not really obvious.
Maybe a different syntax could be implemented, that is more readable and obvious.
But I think, the best approach is to write lot of binary parsers in Roc, for different protocols and formats, then put all of them into an LLM and try out different pattern syntaxes by asking:
It's very easy to design a bad language feature or bad syntax when only thinking about "How cool this feature is, look, this language has this feature!" and not about "How would it help actual code?"
I'm working on a CBOR parser, and found no need for these matchers. Maybe because CBOR is so simple.
Yeh, I have nothing to say about the need or utility of it. However, I think the motivating example for bitstrings is bit packing and working with nonstandard sizes, and destructuring this way is an ergonomic feature derived from that and in line with Elixir's general design.
For example, a better way could be to define packed structs like Zig and pattern match that struct type, instead of matching the number of bits.
Jonathan said:
I think one difference is that Elixir allows you to pattern match on lengths too:
<<head::binary-size(2), rest::binary>> = <<0, 1, 2, 3>>extracts 0 and 1, so for instance if you wanted to chunk out some headers of known size, followed by the rest.
this is doable in Roc too, either:
[_, _] => implies length must be exactly 2[a, b, ..] if bytes.len() == whatever => matches exactlywhat I'm trying to say is that I think we already support everything Elixir supports for this use case, just with different syntax :smile:
I'm not sure - if you wanted to match into a list and destructure out segments of size 3, 10, and 'rest', you would have to write that explicitly as 13 elements + rest then repackage each in new lists. Yes you could use sublist but then you wouldn't be doing it against a match target.
A bitstring also represents an arbitary sequence of bits. If you want to slice out some bits from a list in Roc, I guess you would first represent it as List(U8) then have to do the work to marshal bits when cutting across byte boundaries?
If it is distinct though, I'm not necessarily advocating for it :sweat_smile:
Jonathan said:
I'm not sure - if you wanted to match into a list and destructure out segments of size 3, 10, and 'rest', you would have to write that explicitly as 13 elements + rest then repackage each in new lists. Yes you could use sublist but then you wouldn't be doing it against a match target.
fair, but in that case it doesn't sound like pattern matching would have any readability benefit compared to just calling sublist :smile:
Jonathan said:
A bitstring also represents an arbitary sequence of bits. If you want to slice out some bits from a list in Roc, I guess you would first represent it as List(U8) then have to do the work to marshal bits when cutting across byte boundaries?
you can already do 0b1001_0111 and similar to match bit patterns on individual bytes
that doesn't work across byte boundaries, but if someone has a use case where that's needed I'd want to know about the specific use case first haha
Jonathan said:
If it is distinct though, I'm not necessarily advocating for it :sweat_smile:
Yeh to reiterate, just because I thought it was a distinct feature but not necessarily for Roc :smile:
I think it is a natural feature in the context of Elixir's pattern matching culture
It would be useful if somebody brought an actual pattern from an actual binary protocol, and showed how this matching syntax would improve the code readability or performance.
Because I think it would not.
(Not saying that the current syntax is the most terse or the simplest, but Elixir/Gleam syntax is not how it should be solved.)
Last updated: Oct 15 2026 at 17:56 UTC