@@ -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
@@ -796,140 +789,76 @@ module internal TaskSeqInternal =
796789
797790 }
798791
799- let takeWhile whileKind predicate ( source : TaskSeq < _ >) =
792+ let takeWhile isInclusive predicate ( source : TaskSeq < _ >) =
800793 checkNonNull ( nameof source) source
801794
802795 taskSeq {
803796 use e = source.GetAsyncEnumerator CancellationToken.None
804797 let! notEmpty = e.MoveNextAsync()
805- let mutable more = notEmpty
806-
807- match whileKind, predicate with
808- | Exclusive, Predicate predicate -> // takeWhile
809- while more do
810- let value = e.Current
811- more <- predicate value
812-
813- if more then
814- // yield ONLY if predicate is true
815- yield value
816- let! hasMore = e.MoveNextAsync()
817- more <- hasMore
798+ let mutable hasMore = notEmpty
818799
819- | Inclusive, Predicate predicate -> // takeWhileInclusive
820- while more do
821- let value = e.Current
822- more <- predicate value
823-
824- // yield regardless of result of predicate
825- yield value
826-
827- if more then
828- let! hasMore = e.MoveNextAsync()
829- more <- hasMore
800+ match predicate with
801+ | Predicate synchronousPredicate ->
802+ while hasMore && synchronousPredicate e.Current do
803+ yield e.Current
804+ let! cont = e.MoveNextAsync()
805+ hasMore <- cont
830806
831- | Exclusive, PredicateAsync predicate -> // takeWhileAsync
832- while more do
833- let value = e.Current
834- let! passed = predicate value
835- more <- passed
807+ | PredicateAsync asyncPredicate ->
808+ let mutable predicateHolds = true
836809
837- if more then
838- // yield ONLY if predicate is true
839- yield value
840- let! hasMore = e.MoveNextAsync()
841- more <- hasMore
810+ while hasMore && predicateHolds do // TODO: check perf if `while!` is going to be better or equal
811+ let! predicateIsTrue = asyncPredicate e.Current
842812
843- | Inclusive, PredicateAsync predicate -> // takeWhileInclusiveAsync
844- while more do
845- let value = e.Current
846- let! passed = predicate value
847- more <- passed
813+ if predicateIsTrue then
814+ yield e.Current
815+ let! cont = e.MoveNextAsync()
816+ hasMore <- cont
848817
849- // yield regardless of predicate
850- yield value
818+ predicateHolds <- predicateIsTrue
851819
852- if more then
853- let! hasMore = e.MoveNextAsync()
854- more <- hasMore
820+ // "inclusive" means: always return the item that we pulled, regardless of the result of applying the predicate
821+ // and only stop thereafter. The non-inclusive versions, in contrast, do not return the item under which the predicate is false.
822+ if hasMore && isInclusive then
823+ yield e.Current
855824 }
856825
857- let skipWhile whileKind predicate ( source : TaskSeq < _ >) =
826+ let skipWhile isInclusive predicate ( source : TaskSeq < _ >) =
858827 checkNonNull ( nameof source) source
859828
860829 taskSeq {
861830 use e = source.GetAsyncEnumerator CancellationToken.None
862- let! moveFirst = e.MoveNextAsync()
863- let mutable more = moveFirst
864-
865- match whileKind, predicate with
866- | Exclusive, Predicate predicate -> // skipWhile
867- while more && predicate e.Current do
868- let! hasMore = e.MoveNextAsync()
869- more <- hasMore
870-
871- if more then
872- // yield the last one where the predicate was false
873- // (this ensures we skip 0 or more)
874- yield e.Current
875-
876- while ! e.MoveNextAsync() do // get the rest
877- yield e.Current
878-
879- | Inclusive, Predicate predicate -> // skipWhileInclusive
880- while more && predicate e.Current do
881- let! hasMore = e.MoveNextAsync()
882- more <- hasMore
883-
884- if more then
885- // yield the rest (this ensures we skip 1 or more)
886- while ! e.MoveNextAsync() do
887- yield e.Current
888-
889- | Exclusive, PredicateAsync predicate -> // skipWhileAsync
890- let mutable cont = true
891-
892- if more then
893- let! hasMore = predicate e.Current
894- cont <- hasMore
895-
896- while more && cont do
897- let! moveNext = e.MoveNextAsync()
898-
899- if moveNext then
900- let! hasMore = predicate e.Current
901- cont <- hasMore
902-
903- more <- moveNext
904-
905- if more then
906- // yield the last one where the predicate was false
907- // (this ensures we skip 0 or more)
908- yield e.Current
831+ let! notEmpty = e.MoveNextAsync()
832+ let mutable hasMore = notEmpty
909833
910- while ! e.MoveNextAsync() do // get the rest
911- yield e.Current
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
912840
913- | Inclusive , PredicateAsync predicate -> // skipWhileInclusiveAsync
914- let mutable cont = true
841+ | PredicateAsync asyncPredicate ->
842+ let mutable predicateHolds = true
915843
916- if more then
917- let! hasMore = predicate e.Current
918- cont <- hasMore
844+ while hasMore && predicateHolds do // TODO: check perf if `while!` is going to be better or equal
845+ let! predicateIsTrue = asyncPredicate e.Current
919846
920- while more && cont do
921- let! moveNext = e.MoveNextAsync()
847+ if predicateIsTrue then
848+ // keep skipping
849+ let! cont = e.MoveNextAsync()
850+ hasMore <- cont
922851
923- if moveNext then
924- let! hasMore = predicate e.Current
925- cont <- hasMore
852+ predicateHolds <- predicateIsTrue
926853
927- more <- moveNext
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
928858
929- if more then
930- // get the rest, this gives 1 or more semantics
931- while ! e.MoveNextAsync() do
932- yield e.Current
859+ // propagate the rest
860+ while ! e.MoveNextAsync() do
861+ yield e.Current
933862 }
934863
935864 // Consider turning using an F# version of this instead?
0 commit comments