@@ -95,3 +95,77 @@ module Immutable =
9595 let combined = Array.append prefix restArr
9696 combined |> should equal data
9797 }
98+
99+ module SideEffects =
100+ [<Theory; ClassData( typeof< TestSideEffectTaskSeq>) >]
101+ let ``TaskSeq - splitAt prefix gets first n elements from side - effect seq`` variant = task {
102+ let ts = Gen.getSeqWithSideEffect variant
103+ let! prefix , _ = TaskSeq.splitAt 3 ts
104+ prefix |> should equal [| 1 ; 2 ; 3 |]
105+ }
106+
107+ [<Theory; ClassData( typeof< TestSideEffectTaskSeq>) >]
108+ let ``TaskSeq - splitAt rest yields remaining elements from side - effect seq`` variant = task {
109+ let ts = Gen.getSeqWithSideEffect variant
110+ let! _ , rest = TaskSeq.splitAt 3 ts
111+ let! restArr = TaskSeq.toArrayAsync rest
112+ restArr |> should equal [| 4 .. 10 |]
113+ }
114+
115+ [<Theory; ClassData( typeof< TestSideEffectTaskSeq>) >]
116+ let ``TaskSeq - splitAt prefix and rest together cover all elements of side - effect seq`` variant = task {
117+ let ts = Gen.getSeqWithSideEffect variant
118+ let! prefix , rest = TaskSeq.splitAt 5 ts
119+ let! restArr = TaskSeq.toArrayAsync rest
120+ let combined = Array.append prefix restArr
121+ combined |> should equal [| 1 .. 10 |]
122+ }
123+
124+ [<Fact>]
125+ let ``TaskSeq - splitAt rest is lazy : side effects in rest not triggered until consumed`` () = task {
126+ let mutable restSideEffectCount = 0
127+
128+ let ts = taskSeq {
129+ yield 1
130+ yield 2
131+ yield 3
132+
133+ // These yields are in the "rest" portion
134+ restSideEffectCount <- restSideEffectCount + 1
135+ yield 4
136+ restSideEffectCount <- restSideEffectCount + 1
137+ yield 5
138+ }
139+
140+ let! _prefix , rest = TaskSeq.splitAt 3 ts
141+ // rest has NOT been consumed yet; the side effects in it should not have fired
142+ restSideEffectCount |> should equal 0
143+
144+ // Now consume rest
145+ let! restArr = TaskSeq.toArrayAsync rest
146+ restArr |> should equal [| 4 ; 5 |]
147+ restSideEffectCount |> should equal 2
148+ }
149+
150+ [<Fact>]
151+ let ``TaskSeq - splitAt second evaluation of side - effect seq yields next batch`` () = task {
152+ let mutable i = 0
153+
154+ let ts = taskSeq {
155+ for _ = 1 to 10 do
156+ i <- i + 1
157+ yield i
158+ }
159+
160+ // First split
161+ let! prefix1 , rest1 = TaskSeq.splitAt 4 ts
162+ let! restArr1 = TaskSeq.toArrayAsync rest1
163+ prefix1 |> should equal [| 1 ; 2 ; 3 ; 4 |]
164+ restArr1 |> should equal [| 5 .. 10 |]
165+
166+ // Second split of the same 'ts' uses the same 'i' capture; i is now 10
167+ let! prefix2 , rest2 = TaskSeq.splitAt 4 ts
168+ let! restArr2 = TaskSeq.toArrayAsync rest2
169+ prefix2 |> should equal [| 11 ; 12 ; 13 ; 14 |]
170+ restArr2 |> should equal [| 15 .. 20 |]
171+ }
0 commit comments