Skip to content

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

Merged
merged 6 commits into from
Mar 16, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Implement TaskSeq.removeAt and TaskSeq.removeManyAt
  • Loading branch information
abelbraaksma committed Mar 16, 2024
commit 42269e51eb01bc137830293b72ac78d0e523565b
2 changes: 2 additions & 0 deletions src/FSharp.Control.TaskSeq/TaskSeq.fs
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,8 @@ type TaskSeq private () =

static member insertAt index value source = Internal.insertAt index (One value) source
static member insertManyAt index values source = Internal.insertAt index (Many values) source
static member removeAt index source = Internal.removeAt index source
static member removeManyAt index count source = Internal.removeManyAt index count source

static member except itemsToExclude source = Internal.except itemsToExclude source
static member exceptOfSeq itemsToExclude source = Internal.exceptOfSeq itemsToExclude source
Expand Down
26 changes: 26 additions & 0 deletions src/FSharp.Control.TaskSeq/TaskSeq.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -1300,3 +1300,29 @@ type TaskSeq =
/// <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>
static member insertManyAt: index: int -> values: TaskSeq<'T> -> source: TaskSeq<'T> -> TaskSeq<'T>

/// <summary>
/// Return a new task sequence with the item at the given index removed.
/// </summary>
///
/// <param name="index">The index where the item should be removed.</param>
/// <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>
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.
Copy link
Member

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?

/// If <paramref name="count" /> is negative or zero, no items are removed. If <paramref name="index" />
/// + <paramref name="count" /> is greater than source length, but <paramref name="index" /> is not, then
/// all items until end of sequence are removed.
/// </summary>
///
/// <param name="index">The index where the items should be removed.</param>
Copy link
Member

Choose a reason for hiding this comment

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

the position from which the items should commence being omitted
(depending on if the top level desc changes; if it stays as it is this is obv fine)

/// <param name="count">The number of items to remove.</param>
Copy link
Member

Choose a reason for hiding this comment

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

instead of the legalese in the summary, maybe this could have a terse hint that negative is treated as zero and a count stretching past the end of the input is safe/ignored?

/// <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>
static member removeManyAt: index: int -> count: int -> source: TaskSeq<'T> -> TaskSeq<'T>
37 changes: 37 additions & 0 deletions src/FSharp.Control.TaskSeq/TaskSeqInternal.fs
Original file line number Diff line number Diff line change
Expand Up @@ -896,6 +896,43 @@ module internal TaskSeqInternal =
raiseOutOfBounds (nameof index)
Copy link
Member

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...

}

let removeAt index (source: TaskSeq<'T>) =
if index < 0 then
raiseCannotBeNegative (nameof index)

taskSeq {
let mutable i = 0

for item in source do
if i <> index then
yield item

i <- i + 1

// cannot remove past end of sequence
if i <= index then
raiseOutOfBounds (nameof index)
}

let removeManyAt index count (source: TaskSeq<'T>) =
if index < 0 then
raiseCannotBeNegative (nameof index)

taskSeq {
let mutable i = 0
let indexEnd = index + count

for item in source do
if i < index || i >= indexEnd then
yield item

i <- i + 1

// cannot remove past end of sequence
if i <= index then
raiseOutOfBounds (nameof index)
}

// Consider turning using an F# version of this instead?
// https://github.com/i3arnon/ConcurrentHashSet
type ConcurrentHashSet<'T when 'T: equality>(ct) =
Expand Down