@@ -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,8 +806,10 @@ module internal TaskSeqInternal =
813806
814807 | PredicateAsync asyncPredicate ->
815808 let mutable predicateHolds = true
816- while hasMore && predicateHolds do
809+
810+ while hasMore && predicateHolds do // TODO: check perf if `while!` is going to be better or equal
817811 let! predicateIsTrue = asyncPredicate e.Current
812+
818813 if predicateIsTrue then
819814 yield e.Current
820815 let! cont = e.MoveNextAsync()
@@ -828,51 +823,42 @@ module internal TaskSeqInternal =
828823 yield e.Current
829824 }
830825
831- let skipWhile whileKind predicate ( source : TaskSeq < _ >) =
826+ let skipWhile isInclusive predicate ( source : TaskSeq < _ >) =
832827 checkNonNull ( nameof source) source
833828
834829 taskSeq {
835830 use e = source.GetAsyncEnumerator CancellationToken.None
831+ let! notEmpty = e.MoveNextAsync()
832+ let mutable hasMore = notEmpty
836833
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
834+ match predicate with
835+ | Predicate synchronousPredicate ->
836+ while hasMore && synchronousPredicate e.Current do
837+ // keep skipping
838+ let! cont = e.MoveNextAsync()
839+ hasMore <- cont
845840
846- let mutable cont = true
841+ | PredicateAsync asyncPredicate ->
842+ let mutable predicateHolds = true
847843
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
844+ while hasMore && predicateHolds do // TODO: check perf if `while!` is going to be better or equal
845+ let! predicateIsTrue = asyncPredicate e.Current
857846
858- while ! e.MoveNextAsync() do // propagate the rest
859- yield e.Current
847+ if predicateIsTrue then
848+ // keep skipping
849+ let! cont = e.MoveNextAsync()
850+ hasMore <- cont
860851
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
852+ predicateHolds <- predicateIsTrue
871853
872- while ! e.MoveNextAsync() do // propagate the rest
873- yield e.Current
854+ // "inclusive" means: always skip the item that we pulled, regardless of the result of applying the predicate
855+ // and only stop thereafter. The non-inclusive versions, in contrast, do not skip the item under which the predicate is false.
856+ if hasMore && not isInclusive then
857+ yield e.Current // don't skip, unless inclusive
874858
875- cont <- false
859+ // propagate the rest
860+ while ! e.MoveNextAsync() do
861+ yield e.Current
876862 }
877863
878864 // Consider turning using an F# version of this instead?
0 commit comments