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

List tryRemove function #1093

Open
5 tasks done
aaron-jack-manning opened this issue Nov 7, 2021 · 10 comments
Open
5 tasks done

List tryRemove function #1093

aaron-jack-manning opened this issue Nov 7, 2021 · 10 comments

Comments

@aaron-jack-manning
Copy link

List tryRemove function

My proposal is for a function in the List module (and a similar function for the other collections) to remove the first instance of a specified element in a list, which falls back gracefully when the element isn't found by returning the original list.

Sample code

let rec tryRemove element list =
    match list with
    | [] -> []
    | h :: t -> if h = element then t else h :: tryRemove element t

Currently, I believe the neatest implementation of this when writing F# code is to write a function like the above, as opposed to using standard library functions such as tryFindIndex and removeAt, hence the suggestion for it to exist as its own function.

Considerations

Some consideration should be given to:

  • the name of such a function, since many functions with the try prefix return option type, which the above does not, but it doesn't do so without throwing an exception either.
  • if alternative, similar functions should exist which throw exceptions or return option type to handle cases where the specified element is not found.

Affidavit (please submit!)

Please tick this by placing a cross in the box:

  • This is not a question (e.g. like one you might ask on stackoverflow) and I have searched stackoverflow for discussions of this issue
  • I have searched both open and closed suggestions on this site and believe this is not a duplicate
  • This is not something which has obviously "already been decided" in previous versions of F#. If you're questioning a fundamental design decision that has obviously already been taken (e.g. "Make F# untyped") then please don't submit it.

Please tick all that apply:

  • This is not a breaking change to the F# language design
  • I or my company would be willing to help implement and/or test this

For Readers

If you would like to see this issue implemented, please click the 👍 emoji on this issue. These counts are used to generally order the suggestions by engagement.

@Frassle
Copy link

Frassle commented Nov 7, 2021

Note that both Map and Set have functions called just remove that behave like this. If the element is not found it just returns the input collection. I'd suggest for consistency this would also be called remove.

@aaron-jack-manning
Copy link
Author

Note that both Map and Set have functions called just remove that behave like this. If the element is not found it just returns the input collection. I'd suggest for consistency this would also be called remove.

I didn't realise that. That makes the issue of naming easy to handle, although some care should be made in documentation since Set guarantees uniqueness of elements whereas in this case only the first element will be removed, not all of them, since to remove all you could just use List.where.

@Happypig375
Copy link
Contributor

But why specifically the first element? What are the use cases?

@aaron-jack-manning
Copy link
Author

But why specifically the first element? What are the use cases?

I've needed a function like this many times. Here is one such example. In that case, the list represents a sequence of items that needs to be exhausted, and so having used one, it must be removed. This is because the order in the list isn't really important. However, ultimately the reason to remove the first is because the goal is to remove an element by its value rather than its index (which already exists), and that seems like the most sensible behaviour for such a function (noting again that removing all occurrences can easily be done using List.where).

@Happypig375
Copy link
Contributor

Ah, using a list like a stack.

@Happypig375
Copy link
Contributor

What about removeFirst instead of remove?

@aaron-jack-manning
Copy link
Author

Not quite like a stack, because in a stack you wouldn't look through to remove a certain element. Only like a stack if the list is in the correct order. The only issue with removeFirst is to me that reads like removing the first element of the list, rather than removing the specified element, which is what I'm proposing.

@Tarmil
Copy link

Tarmil commented Nov 8, 2021

I think that just calling it remove is fine because there is precedent: find, tryFind, pick and tryPick return the first matching occurrence.

@Happypig375
Copy link
Contributor

@Tarmil The signatures of those functions return one element or option of one element. remove has no such indication.

@aaron-jack-manning
Copy link
Author

Yes, agreed. The naming inconsistency in an issue here. Maybe removeOne or something?

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

No branches or pull requests

5 participants