Skip to content

Commit

Permalink
refactor(skip+takeWhile): Make impls consistent
Browse files Browse the repository at this point in the history
  • Loading branch information
bartelink authored and abelbraaksma committed Dec 24, 2023
1 parent 35d5bb7 commit cecff30
Showing 1 changed file with 56 additions and 105 deletions.
161 changes: 56 additions & 105 deletions src/FSharp.Control.TaskSeq/TaskSeqInternal.fs
Original file line number Diff line number Diff line change
Expand Up @@ -802,134 +802,85 @@ module internal TaskSeqInternal =
taskSeq {
use e = source.GetAsyncEnumerator CancellationToken.None
let! notEmpty = e.MoveNextAsync()
let mutable more = notEmpty
let mutable cont = notEmpty

match whileKind, predicate with
| Exclusive, Predicate predicate -> // takeWhile
while more do
let value = e.Current
more <- predicate value
let inclusive =
match whileKind with
| Inclusive -> true
| Exclusive -> false

if more then
// yield ONLY if predicate is true
yield value
let! hasMore = e.MoveNextAsync()
more <- hasMore

| Inclusive, Predicate predicate -> // takeWhileInclusive
while more do
let value = e.Current
more <- predicate value

// yield regardless of result of predicate
yield value

if more then
match predicate with
| Predicate predicate -> // takeWhile(Inclusive)?
while cont do
if predicate e.Current then
yield e.Current
let! hasMore = e.MoveNextAsync()
more <- hasMore
cont <- hasMore
else
if inclusive then
yield e.Current

| Exclusive, PredicateAsync predicate -> // takeWhileAsync
while more do
let value = e.Current
let! passed = predicate value
more <- passed
cont <- false

if more then
// yield ONLY if predicate is true
yield value
| PredicateAsync predicate -> // takeWhile(Inclusive)?Async
while cont do
match! predicate e.Current with
| true ->
yield e.Current
let! hasMore = e.MoveNextAsync()
more <- hasMore

| Inclusive, PredicateAsync predicate -> // takeWhileInclusiveAsync
while more do
let value = e.Current
let! passed = predicate value
more <- passed

// yield regardless of predicate
yield value
cont <- hasMore
| false ->
if inclusive then
yield e.Current

if more then
let! hasMore = e.MoveNextAsync()
more <- hasMore
cont <- false
}

let skipWhile whileKind predicate (source: TaskSeq<_>) =
checkNonNull (nameof source) source

taskSeq {
use e = source.GetAsyncEnumerator CancellationToken.None
let! moveFirst = e.MoveNextAsync()
let mutable more = moveFirst

match whileKind, predicate with
| Exclusive, Predicate predicate -> // skipWhile
while more && predicate e.Current do
let! hasMore = e.MoveNextAsync()
more <- hasMore

if more then
// yield the last one where the predicate was false
// (this ensures we skip 0 or more)
yield e.Current

while! e.MoveNextAsync() do // get the rest
yield e.Current

| Inclusive, Predicate predicate -> // skipWhileInclusive
while more && predicate e.Current do
let! hasMore = e.MoveNextAsync()
more <- hasMore

if more then
// yield the rest (this ensures we skip 1 or more)
while! e.MoveNextAsync() do
yield e.Current

| Exclusive, PredicateAsync predicate -> // skipWhileAsync
let mutable cont = true

if more then
let! hasMore = predicate e.Current
cont <- hasMore

while more && cont do
let! moveNext = e.MoveNextAsync()

if moveNext then
let! hasMore = predicate e.Current
cont <- hasMore

more <- moveNext

if more then
// yield the last one where the predicate was false
// (this ensures we skip 0 or more)
yield e.Current
match! e.MoveNextAsync() with
| false -> () // Nothing further to do, no matter what the rules are
| true ->

while! e.MoveNextAsync() do // get the rest
yield e.Current
let exclusive =
match whileKind with
| Exclusive -> true
| Inclusive -> false

| Inclusive, PredicateAsync predicate -> // skipWhileInclusiveAsync
let mutable cont = true

if more then
let! hasMore = predicate e.Current
cont <- hasMore
match predicate with
| Predicate predicate -> // skipWhile(Inclusive)?
while cont do
if predicate e.Current then // spam -> skip
let! hasAnother = e.MoveNextAsync()
cont <- hasAnother
else // Starting the ham
if exclusive then
yield e.Current // return the item as it does not meet the condition for skipping

while more && cont do
let! moveNext = e.MoveNextAsync()
while! e.MoveNextAsync() do // propagate the rest
yield e.Current

if moveNext then
let! hasMore = predicate e.Current
cont <- hasMore
cont <- false
| PredicateAsync predicate -> // skipWhile(Inclusive)?Async
while cont do
match! predicate e.Current with
| true ->
let! hasAnother = e.MoveNextAsync()
cont <- hasAnother
| false -> // We're starting the ham
if exclusive then
yield e.Current // return the item as it does not meet the condition for skipping

more <- moveNext
while! e.MoveNextAsync() do // propagate the rest
yield e.Current

if more then
// get the rest, this gives 1 or more semantics
while! e.MoveNextAsync() do
yield e.Current
cont <- false
}

// Consider turning using an F# version of this instead?
Expand Down

0 comments on commit cecff30

Please sign in to comment.