@@ -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>]
2215type 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