Skip to content

Make List.{take,drop} total - #14124

Merged
nojb merged 1 commit into
ocaml:trunkfrom
dbuenzli:list-drop-take-total
Jul 2, 2025
Merged

nojb merged 1 commit into
ocaml:trunkfrom
dbuenzli:list-drop-take-total

Conversation

@dbuenzli

@dbuenzli dbuenzli commented Jul 2, 2025

Copy link
Copy Markdown
Contributor

See discussion.

Raising is highly non-standard across languages and libraries and the functions have only been there in 5.3 so far.

I think this should go in 5.4 too.

@nojb nojb left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@nojb

nojb commented Jul 2, 2025

Copy link
Copy Markdown
Contributor

I think this should go in 5.4 too.

@Octachron: do you validate?

@nojb nojb added the stdlib label Jul 2, 2025
@Octachron

Copy link
Copy Markdown
Member

If we agree that this PR specification is the right one, then this is a specification bugfix and should be cherry-picked to 5.4.

@nojb

nojb commented Jul 2, 2025

Copy link
Copy Markdown
Contributor

If we agree that this PR specification is the right one, then this is a specification bugfix and should be cherry-picked to 5.4.

OK, thanks. I am of the opinion that this is a specification bugfix, as is @gasche.

Comment thread Changes Outdated
@dbuenzli
dbuenzli force-pushed the list-drop-take-total branch from 6577585 to 6778e39 Compare July 2, 2025 08:54

@gasche gasche left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I agree, and I believe this is worth having in 5.4 to minimize the non-totality version interval.

@nojb
nojb merged commit 6b59d66 into ocaml:trunk Jul 2, 2025
@nojb

nojb commented Jul 2, 2025

Copy link
Copy Markdown
Contributor

CI failure is unrelated. Merging.

nojb pushed a commit that referenced this pull request Jul 2, 2025
@nojb

nojb commented Jul 2, 2025

Copy link
Copy Markdown
Contributor

Cherry-pick to 5.4: da2b221

@dbuenzli
dbuenzli deleted the list-drop-take-total branch July 2, 2025 13:10
@dbuenzli

dbuenzli commented Jul 2, 2025

Copy link
Copy Markdown
Contributor Author

Thanks all!

@giltho

giltho commented Aug 7, 2025

Copy link
Copy Markdown
Contributor

(Late comment, I was looking at the changelog for 5.4 beta)

This specific exception caught a bug in my code yesterday. Specifically, I had an overflow turn my count into a negative value, and then it was passed to List.take. I'm not sure I'd have specifically guarded about negative values by default here, so it was helpful to have it be the default in stdlib.

Raising is highly non-standard across languages

Note also that other languages do tend to prevent negative counts there, e.g. Java raises an exception, Rust prevents the problem by receiving an unsigned integer, Python's itertool raises an exception etc..

I don't necessarily disagree with this PR, I don't think there's necessarily a "best" answer here, but I thought I'd flag it for future similar discussions.

@dbuenzli

dbuenzli commented Aug 7, 2025

Copy link
Copy Markdown
Contributor Author

Personally I also don't have a strong opinion here, I think both view have their own merits.

I do however find totality easier for lazy (in the human sense) edge case reasoning – i.e. rather than proving that n will not be negative, I check that if n is negative it's doesn't have adverse effects on the result of the computation. That kind of reasoning is not available with the raising variant as it kills your computation.

As mentioned here the reason why I wanted to do this change is that I'm contemplating adding corresponding functionality to the String module. Now we could have the raising behaviour there too but most libs that extend the string module tend to have the view of this PR. So if we add these function to String with the raising variants then migrating to the Stdlib.String functionality becomes a painful migration rather than an obvious search and replace.

@giltho

giltho commented Aug 8, 2025

Copy link
Copy Markdown
Contributor

Agreed. An option would be to add some alternative function that is already defensive (e.g. List.take_exn), but then naming is a nightmare because if I have List.take_exn I'd want List.take to return an option for consistency with existing conventions 🫠
Another option would be to return an option in the first place, and then one can do |> Option.value ~default:[] or |> Option.get. It's safer, but it's also unnecessary allocation/computation when you know there's no risk of the integer to be negative.
So yeah, still no strong opinion on my side, it was really about flagging this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants