Hello,
out of curiosity, are there any performance implications on iterating a list with List.walk
vs tail-call recursion with the .. as rest
pattern?
List.walk(some_list, {}, |state, item|
...
)
vs
some_func = |some_list|
[] -> ...
[item, .. as rest] ->
...
some_func(rest)
I see that List.walk
calls get_unsafe
underneath to avoid a bounds check. Can I assume the list destructuring also avoids bounds checks?
And are there any other performance implications to be aware of between the two?
Thanks.
Raw tail recursion is likely slower
Not by a lot, but slower
Llvm might be smart enough to remove the bounds check, but it is not guaranteed.
On top of that, rest is a seamless slice. While those are fast to make, it is still more work than just incrementing an offset.
Overall, probably not something to worry about, but is a minor optimization that could see gains in a very hot loop with essentially no body.
I see,
so rest
would be like me manually doing a rest = List.drop_first(some_list, idx)
inside a List.walk_with_index
or something similar?
No doubt the .. as rest
is convenient for a lot of code
Yeah, rest is equivalent to drop first on the original list.
Which the cost would be incrementing a pointer and decrementing a length.
With a bit of extra orchestration logic
Instead of walk with index where the cost is just an int increment with no extra logic.
hchac has marked this topic as resolved.
Last updated: Jul 06 2025 at 12:14 UTC