@@ -10,6 +10,8 @@ open FSharp.Control
1010//
1111// TaskSeq.takeWhile
1212// TaskSeq.takeWhileAsync
13+ // TaskSeq.takeWhileInclusive
14+ // TaskSeq.takeWhileInclusiveAsync
1315//
1416
1517module EmptySeq =
@@ -28,46 +30,61 @@ module EmptySeq =
2830 |> Task.map ( List.isEmpty >> should be True)
2931
3032// The primary requirement is that items after the item failing the predicate must be excluded
31- module TakeWhileExcludesEverythingAfterFail =
32- [<Fact>]
33- let ``TaskSeq - takeWhile excludes all items after predicate fails`` () =
34- seq { 1 ; 2 ; 2 ; 3 ; 2 ; 1 }
33+ module FiltersAfterFail =
34+ [<Theory; InlineData false ; InlineData true >]
35+ let ``TaskSeq - takeWhile ( Inclusive )? excludes all items after predicate fails`` inclusive =
36+ // The only real difference in semantics between the base and the *Inclusive variant lies in whether the final item is returned
37+ // NOTE the semantics are very clear on only propagating a single failing item in the inclusive case
38+ let f , expected =
39+ if inclusive then TaskSeq.takeWhileInclusive, " ABBC"
40+ else TaskSeq.takeWhile, " ABB"
41+ seq { 1 ; 2 ; 2 ; 3 ; 3 ; 2 ; 1 }
3542 |> TaskSeq.ofSeq
36- |> TaskSeq.takeWhile ( fun x -> x <= 2 )
43+ |> f ( fun x -> x <= 2 )
3744 |> TaskSeq.map char
3845 |> TaskSeq.map ((+) '@' )
3946 |> TaskSeq.toArrayAsync
40- |> Task.map ( String >> should equal " AB " )
47+ |> Task.map ( String >> should equal expected )
4148
42- [<Fact>]
43- let ``TaskSeq - takeWhileAsync excludes all items after after predicate fails`` () =
44- taskSeq { 1 ; 2 ; 2 ; 3 ; 2 ; 1 }
45- |> TaskSeq.takeWhileAsync ( fun x -> task { return x <= 2 })
49+ // Same as preceding test, just with Async functions
50+ [<Theory; InlineData false ; InlineData true >]
51+ let ``TaskSeq - takeWhile ( Inclusive )? Async excludes all items after after predicate fails`` inclusive =
52+ let f , expected =
53+ if inclusive then TaskSeq.takeWhileInclusiveAsync, " ABBC"
54+ else TaskSeq.takeWhileAsync, " ABB"
55+ taskSeq { 1 ; 2 ; 2 ; 3 ; 3 ; 2 ; 1 }
56+ |> f ( fun x -> task { return x <= 2 })
4657 |> TaskSeq.map char
4758 |> TaskSeq.map ((+) '@' )
4859 |> TaskSeq.toArrayAsync
49- |> Task.map ( String >> should equal " AB " )
60+ |> Task.map ( String >> should equal expected )
5061
5162// Covers the fact that it's not sufficient to merely exclude successor items - it's also critical that the enumeration terminates
52- module TakeWhileTerminatesOnFail =
53- [<Fact>]
54- let ``TaskSeq - takeWhile stops consuming after predicate fails`` () =
55- seq { 1 ; 2 ; 3 ; failwith " Too far" }
63+ module StopsEnumeratingAfterFail =
64+ [<Theory; InlineData false ; InlineData true >]
65+ let ``TaskSeq - takeWhile ( Inclusive )? stops consuming after predicate fails`` inclusive =
66+ let f , expected =
67+ if inclusive then TaskSeq.takeWhileInclusive, " ABBC"
68+ else TaskSeq.takeWhile, " ABB"
69+ seq { 1 ; 2 ; 2 ; 3 ; 3 ; failwith " Too far" }
5670 |> TaskSeq.ofSeq
57- |> TaskSeq.takeWhile ( fun x -> x <= 2 )
71+ |> f ( fun x -> x <= 2 )
5872 |> TaskSeq.map char
5973 |> TaskSeq.map ((+) '@' )
6074 |> TaskSeq.toArrayAsync
61- |> Task.map ( String >> should equal " AB " )
75+ |> Task.map ( String >> should equal expected )
6276
63- [<Fact>]
64- let ``TaskSeq - takeWhileAsync stops consuming after predicate fails`` () =
65- taskSeq { 1 ; 2 ; 3 ; failwith " Too far" }
66- |> TaskSeq.takeWhileAsync ( fun x -> task { return x <= 2 })
77+ [<Theory; InlineData false ; InlineData true >]
78+ let ``TaskSeq - takeWhile ( Inclusive )? Async stops consuming after predicate fails`` inclusive =
79+ let f , expected =
80+ if inclusive then TaskSeq.takeWhileInclusiveAsync, " ABBC"
81+ else TaskSeq.takeWhileAsync, " ABB"
82+ taskSeq { 1 ; 2 ; 2 ; 3 ; 3 ; failwith " Too far" }
83+ |> f ( fun x -> task { return x <= 2 })
6784 |> TaskSeq.map char
6885 |> TaskSeq.map ((+) '@' )
6986 |> TaskSeq.toArrayAsync
70- |> Task.map ( String >> should equal " AB " )
87+ |> Task.map ( String >> should equal expected )
7188
7289// This is the base condition as one would expect in actual code
7390let inline cond x = x <> 6
0 commit comments