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

Add warning message to List.Extra (suggested by elmcraft/core-extra#44) #46

Closed
wants to merge 2 commits into from

Conversation

jmbromley
Copy link
Contributor

Add warning message for groupsOf... functions in the documentation in List.Extra as suggested in #44 (comment)

Add warning message for `groupsOf...` functions in the documentation in `List.Extra` as suggested in elmcraft#44 (comment)
@@ -62,6 +62,8 @@ module List.Extra exposing

# Split to groups of given size

> Note that (due to their usage of `List.take` from _elm/core_) the following functions are not always **strictly tail recursive**. For some large tasks it is possible you may run into runtime errors by exceeding the maximum call stack size. For help in this look [here](https://github.com/elmcraft/core-extra.git) and [here](https://github.com/elmcraft/core-extra.git).
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this needs the actual links.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, something went wrong with my copy/paste buffer. Fixed now!

@gampleman
Copy link
Collaborator

This is fine as far as it goes. I wasn't there for the original issue, but is there a reason why the function wasn't made tail recursive to begin with?

@Janiczek
Copy link
Contributor

As the original author: no, there's no specific reason why I didn't write them in a tail-recursive way. Chalk that up to inexperience :) I'd prefer a tailrec version over a fast version.

@jmbromley
Copy link
Contributor Author

I actually made a PR that introduced separate tail recursive versions of the functions here: elm-community/list-extra#165

At the time @Chadtech thought it was too much of a corner case to risk a decrease in efficiency (elm-community/list-extra#164 (comment))

But now that I search the repository more carefully, I see that a few months prior to my PR there had been an effort to make it tail recursive (elm-community/list-extra#157) which was in fact merged, but did not actually fix the issue (see below). In that previous PR the discussion seemed to indicate that it was felt by many that correctness was preferred over efficiency, so maybe I should have pushed for it harder at the time.

The reason the previous PR didn't actually make the functions tail recursive is because it still uses List.take from elm/core which only switches to a tail recursive implementation for lists larger than 1000 elements. This is a problem because the implementation of the groupsOf... family of functions is itself defined by recursion, so you can end up with the non-tail-recursive List.take being called a large number of times and blowing the stack (a real world example is at billstclair/elm-crypto-string#10).

If you want to use a fully tail recursive version in all cases, it should be fairly straightforward to adapt my PR to do so - I'm happy to make a new PR if you'd like?

jmbromley added a commit to jmbromley/core-extra that referenced this pull request Feb 29, 2024
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.
@jmbromley
Copy link
Contributor Author

Okay, so I made a pull request that instead makes groupsOf... fully tail recursive (#47) as an alternative to this PR.

gampleman added a commit that referenced this pull request Mar 23, 2024
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.

Co-authored-by: Jakub Hampl <[email protected]>
@gampleman
Copy link
Collaborator

Closed by #47

@gampleman gampleman closed this Mar 23, 2024
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.

3 participants