Stream: ideas

Topic: Drop n elements from the end of a list


view this post on Zulip Isaac Van Doren (Oct 24 2023 at 21:42):

Right now we have List.drop to drop the first n elements from a list. What do folks think about adding in a function that drops the last n elements from a list? I found myself wanting it a few days ago.

view this post on Zulip Isaac Van Doren (Oct 24 2023 at 21:43):

I’m not sure what a good name for it would be. I think dropFirst and dropLast would make sense but those are already taken.

view this post on Zulip Isaac Van Doren (Oct 24 2023 at 21:44):

Perhaps dropStart and dropEnd?

view this post on Zulip Luke Boswell (Oct 24 2023 at 21:50):

I like it.

view this post on Zulip Brendan Hansknecht (Oct 24 2023 at 21:51):

Double check if we have mirrored apis around first and last

view this post on Zulip Brendan Hansknecht (Oct 24 2023 at 21:51):

I feel like we do with take or split or something, but I don't think the naming is consistent

view this post on Zulip Brendan Hansknecht (Oct 24 2023 at 21:51):

There may be a couple of naming/consistency changes that are wanted here

view this post on Zulip Brendan Hansknecht (Oct 24 2023 at 21:53):

Oh, just realized that you mentioned the other names.

view this post on Zulip Brendan Hansknecht (Oct 24 2023 at 21:54):

I think we should brainstorm names in general cause this could be a repeated API keep or take as well.

view this post on Zulip Brendan Hansknecht (Oct 24 2023 at 21:54):

I also, would personally prefer if dropFirst did what you would expect from dropFirstN.

view this post on Zulip Brendan Hansknecht (Oct 24 2023 at 21:55):

Could also maybe try dropUpTo?

view this post on Zulip Isaac Van Doren (Oct 24 2023 at 22:16):

What’s the policy for renaming functions? Is there a deprecation process or just go for it?

view this post on Zulip Isaac Van Doren (Oct 24 2023 at 22:28):

Could also maybe try dropUpTo?

It’s not clear to me what dropUpTo is supposed to do when I hear that name

view this post on Zulip Richard Feldman (Oct 24 2023 at 22:54):

just go for it :+1:

view this post on Zulip Joshua Warner (Oct 25 2023 at 02:24):

Random thought:
list |> drop (First 5)
list |> drop (Last 5)
list |> drop (Between 2 7)
list |> drop (Where \x -> x > 0)

view this post on Zulip Isaac Van Doren (Oct 25 2023 at 02:40):

Oh wow, that’s a cool idea!

view this post on Zulip Isaac Van Doren (Oct 25 2023 at 02:42):

It is very pleasing to unify all those functions. That said, the downsides that occur to me are that then you need to use more parens, you can’t use the trailing lambda syntax as nicely, and the type signature gets more complicated

view this post on Zulip Isaac Van Doren (Oct 25 2023 at 02:42):

What do others think?

view this post on Zulip Joshua Warner (Oct 25 2023 at 02:55):

Slight extension of that: that thing in parens (call it a predicate) could be used in other functions, e.g. list |> take (Last 5) (just returns the last five elements of the list), and list |> split (Where \x -> x > 0) returns a pair of lists, one where the first list is all the elements that matched the predicate, and the second list is all the elements that didn't. You could even pass that around as a first-class value. Haven't really thought thru the implications/uses for that yet... :thinking:

view this post on Zulip Elias Mulhall (Oct 25 2023 at 02:57):

I think dropIf is nice because it matches up with keepIf and countIf. Otherwise though something like drop : List a, [First Nat, Last Nat, At Nat, Between Nat Nat] -> List a is nice.

view this post on Zulip Elias Mulhall (Oct 25 2023 at 03:03):

Between is maybe a bit awkward because usually when a function takes a range we specify if the start/end is inclusive/exclusive, like List.range list { start: After 2, end: Before 5 }. It could be list |> drop (Within { start: After 2, end: Before 5 }), but that's a bit ornate.

view this post on Zulip Isaac Van Doren (Oct 25 2023 at 03:51):

I think it would be best to either use an approach like this for many applicable functions throughout the builtins or not much at all. But that would be a big change

view this post on Zulip Sven van Caem (Oct 25 2023 at 19:08):

Joshua Warner said:

Random thought:
list |> drop (First 5)
list |> drop (Last 5)
list |> drop (Between 2 7)
list |> drop (Where \x -> x > 0)

I do wonder if adding the extra function argument incurs some runtime cost, or if the extra argument gets optimized out?

view this post on Zulip Brendan Hansknecht (Oct 25 2023 at 19:19):

For always the same tag, should just optimize away

view this post on Zulip Brendan Hansknecht (Oct 25 2023 at 19:19):

Though if optimization fails, will be an extra branch

view this post on Zulip Brendan Hansknecht (Oct 25 2023 at 19:20):

I would generally expect it to inline and optimize away, but confidence in that is hard to say for sure.

view this post on Zulip Brendan Hansknecht (Oct 25 2023 at 19:21):

Personally, I think we should keep it split. I think that Where is better without the parens as dropif. I also think that between is too complex and we shouldn't support it. Look at list.range above for complexities.

view this post on Zulip Brendan Hansknecht (Oct 25 2023 at 19:22):

I would push for just first and last just taking N as an arg. Then is it one simple API with a minor cost of verbosity when dropping exactly one element

view this post on Zulip Isaac Van Doren (Oct 25 2023 at 20:24):

I would push for just first and last just taking N as an arg. Then is it one simple API with a minor cost of verbosity when dropping exactly one element

I agree :check:

view this post on Zulip Declan Joseph Maguire (Oct 26 2023 at 10:18):

Quick q - how are we meant to implement functions like keepIf and dropIf for cases where the condition should depend on the index? It's super common to want to transform the elements of a list based on their indices.

view this post on Zulip Brendan Hansknecht (Oct 26 2023 at 12:32):

Some sort of mapWithIndex followed by a keep. Or some sort of direct walk with extra state

view this post on Zulip Brian Carroll (Oct 26 2023 at 20:08):

Yeah it's worth knowing that walk is the most general of the iteration functions. You can build any of the others from it. And in fact, a lot of them are implemented that way.

view this post on Zulip Declan Joseph Maguire (Oct 26 2023 at 21:52):

I figured that out, but how many bugs have been caused by needing to do your own index maths? It's such an important case that it might be worth giving a little help

view this post on Zulip Brendan Hansknecht (Oct 26 2023 at 21:55):

I think we have walk with index as well

view this post on Zulip Declan Joseph Maguire (Oct 26 2023 at 21:58):

Oh good. Then all that's left is how to make keepIf and dropifwork nicely with indices. Maybe just play with its type so it can take either a function that accepts the list type alone, or the list type and a nat, with the innards branching on the choice?

view this post on Zulip Brendan Hansknecht (Oct 26 2023 at 22:20):

If you are using indices, do you need it as part of keepIf? I would expect you would first extra a sublist or similar. When would both be needed but sublist not work?


Last updated: Jun 16 2026 at 16:19 UTC