@@ -11,13 +11,6 @@ type internal AsyncEnumStatus =
11
11
| WithCurrent
12
12
| AfterAll
13
13
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
-
21
14
[<Struct>]
22
15
type internal TakeOrSkipKind =
23
16
/// use the Seq.take semantics, raises exception if not enough elements
@@ -796,140 +789,76 @@ module internal TaskSeqInternal =
796
789
797
790
}
798
791
799
- let takeWhile whileKind predicate ( source : TaskSeq < _ >) =
792
+ let takeWhile isInclusive predicate ( source : TaskSeq < _ >) =
800
793
checkNonNull ( nameof source) source
801
794
802
795
taskSeq {
803
796
use e = source.GetAsyncEnumerator CancellationToken.None
804
797
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
818
799
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
830
806
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
836
809
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
842
812
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
848
817
849
- // yield regardless of predicate
850
- yield value
818
+ predicateHolds <- predicateIsTrue
851
819
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
855
824
}
856
825
857
- let skipWhile whileKind predicate ( source : TaskSeq < _ >) =
826
+ let skipWhile isInclusive predicate ( source : TaskSeq < _ >) =
858
827
checkNonNull ( nameof source) source
859
828
860
829
taskSeq {
861
830
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
909
833
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
912
840
913
- | Inclusive , PredicateAsync predicate -> // skipWhileInclusiveAsync
914
- let mutable cont = true
841
+ | PredicateAsync asyncPredicate ->
842
+ let mutable predicateHolds = true
915
843
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
919
846
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
922
851
923
- if moveNext then
924
- let! hasMore = predicate e.Current
925
- cont <- hasMore
852
+ predicateHolds <- predicateIsTrue
926
853
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
928
858
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
933
862
}
934
863
935
864
// Consider turning using an F# version of this instead?
0 commit comments