-
Notifications
You must be signed in to change notification settings - Fork 8
Implement TaskSeq.insertAt
, updateAt
, removeAt
, insertManyAt
, removeManyAt
#236
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
Conversation
c57f5e7
to
391f438
Compare
This is ready. Now all that's left is |
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.
Drinking in the completeness of your tests always just fills me with self loathing
Luckily that pain can fuel nit picking and general devil's advocate "just asking questions" routine.
In other words, please take as little or as much of this as you wish, especially given the review is long after the work...
@@ -1275,3 +1276,65 @@ type TaskSeq = | |||
/// <exception cref="T:ArgumentNullException">Thrown when the input task sequence is null.</exception> | |||
static member foldAsync: | |||
folder: ('State -> 'T -> #Task<'State>) -> state: 'State -> source: TaskSeq<'T> -> Task<'State> | |||
|
|||
/// <summary> | |||
/// Return a new task sequence with a new item inserted before the given index. |
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.
ye olde yields vs returns thing triggering in my head
Yes, all functions return things
the <returns>
expresses it in that way and it's clear.
But in general mapping a sequence that's lazy to another thing that's still lazy
Thoughts? If there is prior art art/or it makes any sense to you I might do a walk to see if such language makes sense to apply across the board for all functions that return some mapped/altered rendition of some input?
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.
a new item -> an additional item?
or
a specified item
/ value?
let ``TaskSeq-updateAt(0) will execute side effects at start of sequence`` () = | ||
// NOTE: while not strictly necessary, this mirrors behavior of Seq.updateAt | ||
|
||
let mutable x = 42 // for this test, the potential mutation should not actually occur |
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.
not?
/// Return a new task sequence with a new item inserted before the given index. | ||
/// </summary> | ||
/// | ||
/// <param name="index">The index where the item should be inserted.</param> |
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.
where -> at which ?
/// <param name="source">The input task sequence.</param> | ||
/// <returns>The result task sequence.</returns> | ||
/// <exception cref="T:ArgumentNullException">Thrown when the input task sequence is null.</exception> | ||
/// <exception cref="T:ArgumentException">Thrown when index is below 0 or greater than source length.</exception> |
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.
below is atypical, unless it aligns with something I'd say less than?
you use the term negative elsewhere and that feels best?
static member removeAt: index: int -> source: TaskSeq<'T> -> TaskSeq<'T> | ||
|
||
/// <summary> | ||
/// Return a new task sequence with the number of items starting at a given index removed. |
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.
Return a new task sequence with the number of items starting at a given index removed
Yields a new task sequence omitting the specified number of items at the given index
- the removed is already in the name ? and it does not convey that there never was a materialized thing that things are being chopped out of; they're kinda just skipped. Maybe that's obvious, but I'm thinking of people that are hearing index and at index and thinking mentally of arrays. I guess I don't have beginner cred here so I don't know; i.e. it's just a suggestions/thought
Am also thinking that the term position
might make sense somewhere, but you use index consistenly and I think its a good term
also instead of omitting, maybe dropping?
@@ -49,6 +49,11 @@ type internal InitAction<'T, 'TaskT when 'TaskT :> Task<'T>> = | |||
| InitAction of init_item: (int -> 'T) | |||
| InitActionAsync of async_init_item: (int -> 'TaskT) | |||
|
|||
[<Struct>] | |||
type internal ManyOrOne<'T> = |
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 not base case first in the naming?
let inline raiseCannotBeNegative name = invalidArg name "The value must be non-negative." | ||
|
||
let inline raiseOutOfBounds name = | ||
invalidArg name "The value or index must be within the bounds of the task sequence." |
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 seems very wooly and prob should be just 2 helpers with specific messages?
if I say "value or" and didnt know anything I'd wonder what that is about, while index is pretty clear
Also should it be ArgumentOutOfRangeException?
@@ -57,7 +62,10 @@ module internal TaskSeqInternal = | |||
|
|||
let inline raiseEmptySeq () = invalidArg "source" "The input task sequence was empty." | |||
|
|||
let inline raiseCannotBeNegative name = invalidArg name "The value must be non-negative" | |||
let inline raiseCannotBeNegative name = invalidArg name "The value must be non-negative." |
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.
Should it be ArgumentOutOfRangeException?
I'm fine with a generic invalidArg with a message tho; just being a devil's advocate
|
||
for item in source do | ||
if i = index then | ||
match valueOrValues with |
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.
name suggests one or many, but you handle the cases in many or one order ;P
| One value -> yield value | ||
|
||
if i < index then | ||
raiseOutOfBounds (nameof index) |
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.
if this is a dynamic case, like this, is argument exception appropriate?
should it not be invalidOperationExceptions? IndexOutOfRangeExpcetions?
I know I suggested that ArgumentOutOfRangeException might be better too, but it's kinda wrong for the same reasons no?
Only raising questions; I assume this is derived from what Seq does/decided...
Part of the push for good coverage of surface area functions, see #208 for an overview. This implements
insertAt
,updateAt
,removeAt
,insertManyAt
,removeManyAt
andmaxByAsync
.We won't be implementing
updateManyAt
unless there's a strong use case. We skip it for the same reasons it was skipped in FSharp.Core forSeq
: fsharp/fslang-suggestions#1047 (comment).Each of these behave exactly like their
Seq
counterparts:null
inputAs before, the xml doc blibs have been taken from
seq.fs
and modified a bit for readability and applicability toTaskSeq
.The signatures are as follows:
TODO list:
TaskSeq.insertAt
TaskSeq.insertManyAt
TaskSeq.removeAt
TaskSeq.removeManyAt
TaskSeq.updateAt