-
Notifications
You must be signed in to change notification settings - Fork 847
[RFC FS-1113] Additions to collection functions #11888
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
[RFC FS-1113] Additions to collection functions #11888
Conversation
|
@dsyme I found out that the Map.Values implementation collides with internal Map.Values extension in illib.fs - MapAutoOpens module which returns a list instead of seq. This is the reason the solution right now doesn't build. Since it's not part of the spec you provided I'll remove it from this PR. That said I see it's something that IS used, so let me know if you'd like me to take a look at it in a separate PR. |
dsyme
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking good.
Based on the suggestion discussion and looknig at the implementation I think we should at least drop updateManyAt across the board. It is just too corner-case.
I'll discuss on the suggestion further
… illib.fs and NameResolution.fs to be compatible, update surface area
dsyme
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking great, just a few comments on the benchmarking
# F# RFC FS-1113 - Add insert/remove/update functions for collections, also Keys/Values for Map The design suggestion [Additions to collections for insert/update/ remove](fsharp/fslang-suggestions#1047) has been marked "approved in principle". This RFC covers the detailed proposal for this suggestion. - [x] [Suggestion](fsharp/fslang-suggestions#1047) - [x] Approved in principle - [x] [Implementation](dotnet/fsharp#11888) - [Discussion](https://github.com/fsharp/fslang-design/discussions/FILL-ME-IN) # Summary 1. Add insert/remove/update functions to List, Array, Seq, Map to improve them as workhorse functional collections 2. Add `Keys` and `Values` properties to Map # Motivation All the above are commonly useful. # Detailed design We add the following: ```fsharp module List = /// Return a new list with the item at a given index removed /// If the index is outside the range of the list then it is ignored. val removeAt: index: int -> source: 'T list -> 'T list /// Return a new list with the number of items starting at a given index removed. /// If index is outside 0..source.Length-1 then it is ignored. val removeManyAt: index: int -> count: int -> source: 'T list -> 'T list /// Return a new list with the item at a given index set to the new value. If /// index is outside 0..source.Length-1 an exception is raised. val updateAt: index: int -> value: 'T -> source: 'T list -> 'T list /// Return a new list with a new item inserted before the given index.The index may be source.Length to /// include extra elements at the end of the list. If /// index is outside 0..source.Length an exception is raised. val insertAt: index: int -> value: 'T -> source: 'T list -> 'T list /// Return a new list with new items inserted before the given index. The index may be source.Length to /// include extra elements at the end of the list. /// If index is outside 0..source.Length an exception is raised. val insertManyAt: index: int -> values: seq<'T> -> source: 'T list -> 'T list module Array = /// Return a new array with the item at a given index removed /// If the index is outside the range of the array then it is ignored. val removeAt: index: int -> source: 'T[] -> 'T[] /// Return a new array with the number of items starting at a given index removed. /// If an implied item index is outside the range of the array then it is ignored. val removeManyAt: index: int -> count: int -> source: 'T[] -> 'T[] /// Return a new array with the item at a given index set to the new value. If /// index is outside 0..source.Length-1 an exception is raised. val updateAt: index: int -> value: 'T -> source: 'T[] -> 'T[] /// Return a new array with a new item inserted before the given index. The index may be source.Length to /// include extra elements at the end of the array. If /// index is outside 0..source.Length than source.Length an exception is raised. val insertAt: index: int -> value: 'T -> source: 'T[] -> 'T[] /// Return a new array with new items inserted before the given index. The index may be source.Length to /// include extra elements at the end of the array. If index is outside 0..source.Length an exception is raised. val insertManyAt: index: int -> values: seq<'T> -> source: 'T[] -> 'T[] module Seq = /// Return a new ssequence which, when iterated, will have the item at a given index removed /// If the index is outside the range of valid indexes for the sequence then it is ignored. val removeAt: index: int -> source: seq<'T> -> seq<'T> /// Return a new sequence which, when iterated, will have the given count of items starting at a given index removed. /// If any implied item index is outside the range of valid indexes for the sequence then it is ignored. val removeManyAt: index: int -> count: int -> source: seq<'T> -> seq<'T> /// Return a new sequence which, when iterated, will return the given item for the given index, and /// otherwise return the items from source. If index is below zero an exception is raised immediately. /// If the index is beyond the range on the source sequence the update is ignored. val updateAt: index: int -> value: 'T -> source: seq<'T> -> seq<'T> /// Return a new sequence which, when iterated, includes a new item inserted before the given index. The index may be source.Length to /// include extra elements at the end of the sequence. If /// index is outside 0..source.Length than source.Length an exception is raised. val insertAt: index: int -> value: 'T -> source: seq<'T> -> seq<'T> /// Return a new sequence which, when iterated, will include additional items given by values, starting /// at the given index. The index may be source.Length to /// include extra elements at the end of the sequence. /// If index is outside 0..source.Length an exception is raised. val insertManyAt: index: int -> values: seq<'T> -> source: seq<'T> -> seq<'T> ``` # Drawbacks Adds extra functions to FSharp.Core # Alternatives See suggestion discussion thread for discusssion on `updateManyAt` and also other naming alternatives. # Compatibility Not a breaking change # Unresolved questions None
|
I've added an RFC for this here: https://github.com/fsharp/fslang-design/blob/main/preview/FS-1113-insert-remove-update-functions.md |
|
@uxsoft I updated to
|
|
@uxsoft Thank you for this contribution! |
|
Thank you for your guidance! |
|
Nice work, now I can get rid of some of my 'extensions' in the near future :) I am not sure if this is the right place to ask this, as this is already merged. Also the tests should verify this if this is added. |
Yes, I agree. It's also interesting to think whether things like "get me the middle key in the ordering of keys" will run efficiently or not I haven't checked. Probably not |
|
I can open a new PR with these small changes if you'd like |
Yes you're correct, thanks |
Yes, please make the additions to the doc comments |
| |> List.filter (function | ||
| |> Seq.filter (function | ||
| | Item.UnqualifiedType _ -> false | ||
| | Item.Value v -> not v.IsMember | ||
| | _ -> true) | ||
| |> List.filter (ItemIsUnseen ad g ncenv.amap m >> not) | ||
| |> Seq.filter (ItemIsUnseen ad g ncenv.amap m >> not) | ||
| |> Seq.toList |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this change was needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I doubt it was necessary
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Notice the implementation of values in illib.fs returns a list and the public one an ICollection. The old code expecting a List would not compile if I didn't change it to seq.
If there was a better solution I missed, I'd be happy to learn.
| static member Empty : Map<'Key, 'Value> = Map.empty | ||
|
|
||
| member x.Values = [ for KeyValue(_, v) in x -> v ] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@auduchinok Hmmmm could you please open a separate issue about this. I agree public non-pre-release FCS should indeed only use a public non-pre-release FCS.
However if FCS in pre-release and the release plan is matching FSharp.Core than it is ok

Suggestion approved in principle: fsharp/fslang-suggestions#1047
RFC FS-1113 https://github.com/fsharp/fslang-design/blob/main/preview/FS-1113-insert-remove-update-functions.md