In Elm, it is common to pattern match a list using head and tail.
tail : List a -> Maybe (List a)
tail list =
case list of
x :: xs ->
Just xs
[] ->
Nothing
What is the equivalent for Elms x::xs
in Roc?
From the pattern matching examples in the tutorial, it is not apparent to me how i would get the tail:
when myList is
[] -> 0 # the list is empty
[Foo, ..] -> 1 # it starts with a Foo tag
[_, ..] -> 2 # it contains at least one element, which we ignore
[Foo, Bar, ..] -> 3 # it starts with a Foo tag followed by a Bar tag
[Foo, Bar, Baz] -> 4 # it has exactly 3 elements: Foo, Bar, and Baz
[Foo, a, ..] -> 5 # its first element is Foo, and its second we name `a`
[Ok a, ..] -> 6 # it starts with an Ok containing a payload named `a`
[.., Foo] -> 7 # it ends with a Foo tag
[A, B, .., C, D] -> 8 # it has certain elements at the beginning and end
It's this: :smile:
when list is
[ head, .. as tail ] -> Ok tail
[] -> Err ListWasEmpty
Tutorial needs updating, that is a new feature.
I created https://github.com/roc-lang/roc/issues/6223 for this.
I have a related question. I don't see a List.tail
function, is List.dropFirst 1
the best way to do this? Is there a performance difference between this and the when list is
approach?
It may have been a performance issue before... I'm not sure. But I wouldn't be surprised if that was the reason, and now with Seamless Slices implemented it may no longer be the case and we should discuss the pro's of adding something like that.
Probably could add it now.
And yeah, would be exactly the same as the when ... is
or List.dropFirst 1
So all versions should perform great now
as it was marked as a good first issue i thought i'd give it a go. https://github.com/roc-lang/roc/pull/6229
Luke Boswell said:
It may have been a performance issue before... I'm not sure. But I wouldn't be surprised if that was the reason, and now with Seamless Slices implemented it may no longer be the case and we should discuss the pro's of adding something like that.
Oh! This comment made me realise that my understanding of performance in Roc is a bit dated. And I did not find anything in the docs about seamless slices. Like, with seamless slices, is it still more performant to append values to the end of the list instead of prepending values at the front?
In Elm and many functional languages, it's common to work with lists as head+tail because they're linked lists, where random access is slow, and working at the head of the list is easy.
In Roc, Lists are are arrays under the hood, a big continuous chunk of memory, so random access is just fine. So it's not as necessary to deconstruct a list like this.
I assumed List was a linked list due to its name and similarity to other languages. Is there a reason it is named List instead of Array?
Could we clarify the type of list in the docs somewhere? Perhaps at the top of the List docs?
yeah array means static length in some languages (C, Rust)
Naming of this things is always confusing (array, list, vector, collection?, probably more). I think List
is fine, but we should add to the docs how it works under the hood, since it's often important for performance
Python and Java both use List
in a way that isn't specific to linked lists, and they're 2 of the 3 most popular languages in the world so I think that's some solid precedent :big_smile:
Specifically I think a guide in the language reference over here https://www.roc-lang.org/docs#language-reference
Last updated: Jul 06 2025 at 12:14 UTC