Skip to content

Commit cbe05a7

Browse files
committed
Also simplify skipWhile and skipWhileInclusive (plus async variants)
1 parent 4ed6ba5 commit cbe05a7

File tree

2 files changed

+30
-48
lines changed

2 files changed

+30
-48
lines changed

src/FSharp.Control.TaskSeq/TaskSeq.fs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -303,10 +303,10 @@ type TaskSeq private () =
303303
static member takeWhileAsync predicate source = Internal.takeWhile false (PredicateAsync predicate) source
304304
static member takeWhileInclusive predicate source = Internal.takeWhile true (Predicate predicate) source
305305
static member takeWhileInclusiveAsync predicate source = Internal.takeWhile true (PredicateAsync predicate) source
306-
static member skipWhile predicate source = Internal.skipWhile Exclusive (Predicate predicate) source
307-
static member skipWhileAsync predicate source = Internal.skipWhile Exclusive (PredicateAsync predicate) source
308-
static member skipWhileInclusive predicate source = Internal.skipWhile Inclusive (Predicate predicate) source
309-
static member skipWhileInclusiveAsync predicate source = Internal.skipWhile Inclusive (PredicateAsync predicate) source
306+
static member skipWhile predicate source = Internal.skipWhile false (Predicate predicate) source
307+
static member skipWhileAsync predicate source = Internal.skipWhile false (PredicateAsync predicate) source
308+
static member skipWhileInclusive predicate source = Internal.skipWhile true (Predicate predicate) source
309+
static member skipWhileInclusiveAsync predicate source = Internal.skipWhile true (PredicateAsync predicate) source
310310

311311
static member tryPick chooser source = Internal.tryPick (TryPick chooser) source
312312
static member tryPickAsync chooser source = Internal.tryPick (TryPickAsync chooser) source

src/FSharp.Control.TaskSeq/TaskSeqInternal.fs

Lines changed: 26 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,6 @@ type internal AsyncEnumStatus =
1111
| WithCurrent
1212
| AfterAll
1313

14-
[<Struct>]
15-
type internal WhileKind =
16-
/// The item under test is included (or skipped) even when the predicate returns false
17-
| Inclusive
18-
/// The item under test is always excluded (or not skipped)
19-
| Exclusive
20-
2114
[<Struct>]
2215
type internal TakeOrSkipKind =
2316
/// use the Seq.take semantics, raises exception if not enough elements
@@ -813,7 +806,7 @@ module internal TaskSeqInternal =
813806

814807
| PredicateAsync asyncPredicate ->
815808
let mutable predicateHolds = true
816-
while hasMore && predicateHolds do
809+
while hasMore && predicateHolds do // TODO: check perf if `while!` is going to be better or equal
817810
let! predicateIsTrue = asyncPredicate e.Current
818811
if predicateIsTrue then
819812
yield e.Current
@@ -828,51 +821,40 @@ module internal TaskSeqInternal =
828821
yield e.Current
829822
}
830823

831-
let skipWhile whileKind predicate (source: TaskSeq<_>) =
824+
let skipWhile isInclusive predicate (source: TaskSeq<_>) =
832825
checkNonNull (nameof source) source
833826

834827
taskSeq {
835828
use e = source.GetAsyncEnumerator CancellationToken.None
829+
let! notEmpty = e.MoveNextAsync()
830+
let mutable hasMore = notEmpty
836831

837-
match! e.MoveNextAsync() with
838-
| false -> () // Nothing further to do, no matter what the rules are
839-
| true ->
840-
841-
let exclusive =
842-
match whileKind with
843-
| Exclusive -> true
844-
| Inclusive -> false
845-
846-
let mutable cont = true
847-
848-
match predicate with
849-
| Predicate predicate -> // skipWhile(Inclusive)?
850-
while cont do
851-
if predicate e.Current then // spam -> skip
852-
let! hasAnother = e.MoveNextAsync()
853-
cont <- hasAnother
854-
else // Starting the ham
855-
if exclusive then
856-
yield e.Current // return the item as it does not meet the condition for skipping
832+
match predicate with
833+
| Predicate synchronousPredicate ->
834+
while hasMore && synchronousPredicate e.Current do
835+
// keep skipping
836+
let! cont = e.MoveNextAsync()
837+
hasMore <- cont
857838

858-
while! e.MoveNextAsync() do // propagate the rest
859-
yield e.Current
839+
| PredicateAsync asyncPredicate ->
840+
let mutable predicateHolds = true
841+
while hasMore && predicateHolds do // TODO: check perf if `while!` is going to be better or equal
842+
let! predicateIsTrue = asyncPredicate e.Current
843+
if predicateIsTrue then
844+
// keep skipping
845+
let! cont = e.MoveNextAsync()
846+
hasMore <- cont
860847

861-
cont <- false
862-
| PredicateAsync predicate -> // skipWhile(Inclusive)?Async
863-
while cont do
864-
match! predicate e.Current with
865-
| true ->
866-
let! hasAnother = e.MoveNextAsync()
867-
cont <- hasAnother
868-
| false -> // We're starting the ham
869-
if exclusive then
870-
yield e.Current // return the item as it does not meet the condition for skipping
848+
predicateHolds <- predicateIsTrue
871849

872-
while! e.MoveNextAsync() do // propagate the rest
873-
yield e.Current
850+
// "inclusive" means: always skip the item that we pulled, regardless of the result of applying the predicate
851+
// and only stop thereafter. The non-inclusive versions, in contrast, do not skip the item under which the predicate is false.
852+
if hasMore && not isInclusive then
853+
yield e.Current // don't skip, unless inclusive
874854

875-
cont <- false
855+
// propagate the rest
856+
while! e.MoveNextAsync() do
857+
yield e.Current
876858
}
877859

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

0 commit comments

Comments
 (0)