Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make groupsOf... family of functions fully tail recursive. #47

Merged
merged 7 commits into from
Mar 23, 2024

Conversation

jmbromley
Copy link
Contributor

This commit makes the groupsOf... family of functions fully tail recursive by forcing them to use the tail recursive version of List.take (normally List.take is only tail recursive for lists larger than 1000, but since the groupsOf... functions are themselves recursive this can result in potential call stack overflow from the successive accumulation of (up to) 1000-long non-recursive List.take calls during the recursion).

This is an alternative to PR #46 which would instead just add a note to the documentation warning users about the potential overflow.

This commit makes the `groupsOf...` family of functions fully tail recursive by forcing them to use the tail recursive version of List.take (normally List.take is only tail recursive for lists larger than 1000, but since the `groupsOf...` functions are themselves recursive  this can result in potential call stack overflow from the successive accumulation of (up to) 1000-long non-recursive List.take calls during the recursion).

This is an alternative to PR elmcraft#46 which would instead just add a note to the documentation warning users about the potential overflow.
src/List/Extra.elm Outdated Show resolved Hide resolved
@gampleman
Copy link
Collaborator

Also (if you can be bothered or if anyone else wants to pitch in), I'd love to see a benchmark (see our benchmarks directory for samples) comparing the two versions on performance.

@Janiczek
Copy link
Contributor

Janiczek commented Mar 1, 2024

There's never enough procrastination at work...

Screenshot 2024-03-01 at 16 24 57

Source: https://gist.github.com/Janiczek/b8e3f66cba281aac1dba4ea7dd80b709

@Janiczek
Copy link
Contributor

Janiczek commented Mar 1, 2024

I'm also gonna run a benchmark on scaling the step, since that's the part that most relates to the takeTailRec, which is the only code change between the old and new groupsOf* functions.

@Janiczek
Copy link
Contributor

Janiczek commented Mar 1, 2024

Screenshot 2024-03-01 at 19 31 29

Screenshot 2024-03-01 at 19 31 36

Screenshot 2024-03-01 at 19 31 45

Code is in the same gist as ScaleBenchmark.elm

@Janiczek
Copy link
Contributor

Janiczek commented Mar 1, 2024

From my point of view, let's ship it!

@gampleman
Copy link
Collaborator

@Janiczek I added your code to the PR (we tend to keep benchmarking code around to have a better record of performance work).

I have slightly different looking results on Safari:

Screenshot 2024-03-21 at 17 33 53

Eye-balling it, looks like about 30% performance drop.

@gampleman gampleman merged commit 2ab7ca0 into elmcraft:master Mar 23, 2024
2 checks passed
@gampleman
Copy link
Collaborator

Thanks @jmbromley and @Janiczek for taking the time on this one!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants