Skip to content

Commit dbb521e

Browse files
github-actions[bot]Repo AssistCopilotdsyme
authored
[Repo Assist] Add AsyncSeq.zip3, zipWith3, zipWithAsync3 (#254)
* Add AsyncSeq.zip3, zipWith3, zipWithAsync3 Three new combinators mirroring Seq.zip3 for combining three async sequences: - zip3: combines three async sequences into a sequence of triples - zipWith3: applies a 3-argument function across three async sequences - zipWithAsync3: async variant of zipWith3 3 new tests added; all 237 tests pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * ci: trigger CI checks --------- Co-authored-by: Repo Assist <repo-assist@github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Don Syme <dsyme@users.noreply.github.com>
1 parent dba4810 commit dbb521e

File tree

3 files changed

+74
-0
lines changed

3 files changed

+74
-0
lines changed

src/FSharp.Control.AsyncSeq/AsyncSeq.fs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1552,6 +1552,32 @@ module AsyncSeq =
15521552
let zipWithIndexAsync (f:int64 -> 'T -> Async<'U>) (s:AsyncSeq<'T>) : AsyncSeq<'U> =
15531553
mapiAsync f s
15541554

1555+
let zipWithAsync3 (f:'T1 -> 'T2 -> 'T3 -> Async<'U>) (source1:AsyncSeq<'T1>) (source2:AsyncSeq<'T2>) (source3:AsyncSeq<'T3>) : AsyncSeq<'U> = asyncSeq {
1556+
use ie1 = source1.GetEnumerator()
1557+
use ie2 = source2.GetEnumerator()
1558+
use ie3 = source3.GetEnumerator()
1559+
let! move1 = ie1.MoveNext()
1560+
let! move2 = ie2.MoveNext()
1561+
let! move3 = ie3.MoveNext()
1562+
let b1 = ref move1
1563+
let b2 = ref move2
1564+
let b3 = ref move3
1565+
while b1.Value.IsSome && b2.Value.IsSome && b3.Value.IsSome do
1566+
let! res = f b1.Value.Value b2.Value.Value b3.Value.Value
1567+
yield res
1568+
let! move1n = ie1.MoveNext()
1569+
let! move2n = ie2.MoveNext()
1570+
let! move3n = ie3.MoveNext()
1571+
b1 := move1n
1572+
b2 := move2n
1573+
b3 := move3n }
1574+
1575+
let zip3 (source1:AsyncSeq<'T1>) (source2:AsyncSeq<'T2>) (source3:AsyncSeq<'T3>) : AsyncSeq<'T1 * 'T2 * 'T3> =
1576+
zipWithAsync3 (fun a b c -> async.Return (a, b, c)) source1 source2 source3
1577+
1578+
let zipWith3 (f:'T1 -> 'T2 -> 'T3 -> 'U) (source1:AsyncSeq<'T1>) (source2:AsyncSeq<'T2>) (source3:AsyncSeq<'T3>) : AsyncSeq<'U> =
1579+
zipWithAsync3 (fun a b c -> f a b c |> async.Return) source1 source2 source3
1580+
15551581
let zappAsync (fs:AsyncSeq<'T -> Async<'U>>) (s:AsyncSeq<'T>) : AsyncSeq<'U> =
15561582
zipWithAsync (|>) s fs
15571583

src/FSharp.Control.AsyncSeq/AsyncSeq.fsi

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,18 @@ module AsyncSeq =
406406
/// The resulting sequence stops when either of the argument sequences stop.
407407
val zipWithParallel : mapping:('T1 -> 'T2 -> 'U) -> source1:AsyncSeq<'T1> -> source2:AsyncSeq<'T2> -> AsyncSeq<'U>
408408

409+
/// Combines three asynchronous sequences using the specified asynchronous function.
410+
/// The resulting sequence stops when any of the argument sequences stop.
411+
val zipWithAsync3 : mapping:('T1 -> 'T2 -> 'T3 -> Async<'U>) -> source1:AsyncSeq<'T1> -> source2:AsyncSeq<'T2> -> source3:AsyncSeq<'T3> -> AsyncSeq<'U>
412+
413+
/// Combines three asynchronous sequences into a sequence of triples.
414+
/// The resulting sequence stops when any of the argument sequences stop.
415+
val zip3 : source1:AsyncSeq<'T1> -> source2:AsyncSeq<'T2> -> source3:AsyncSeq<'T3> -> AsyncSeq<'T1 * 'T2 * 'T3>
416+
417+
/// Combines three asynchronous sequences using the specified function.
418+
/// The resulting sequence stops when any of the argument sequences stop.
419+
val zipWith3 : mapping:('T1 -> 'T2 -> 'T3 -> 'U) -> source1:AsyncSeq<'T1> -> source2:AsyncSeq<'T2> -> source3:AsyncSeq<'T3> -> AsyncSeq<'U>
420+
409421
/// Builds a new asynchronous sequence whose elements are generated by
410422
/// applying the specified function to all elements of the input sequence.
411423
///

tests/FSharp.Control.AsyncSeq.Tests/AsyncSeqTests.fs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -895,6 +895,42 @@ let ``AsyncSeq.zipWithAsyncParallel``() =
895895
let expected = Seq.zip la lb |> Seq.map ((<||) (+)) |> AsyncSeq.ofSeq
896896
Assert.True(EQ expected actual)
897897

898+
[<Test>]
899+
let ``AsyncSeq.zip3``() =
900+
for la in [ []; [1]; [1;2;3;4;5] ] do
901+
for lb in [ []; [1]; [1;2;3;4;5] ] do
902+
for lc in [ []; [1]; [1;2;3;4;5] ] do
903+
let a = la |> AsyncSeq.ofSeq
904+
let b = lb |> AsyncSeq.ofSeq
905+
let c = lc |> AsyncSeq.ofSeq
906+
let actual = AsyncSeq.zip3 a b c
907+
let expected = Seq.zip3 la lb lc |> AsyncSeq.ofSeq
908+
Assert.True(EQ expected actual)
909+
910+
[<Test>]
911+
let ``AsyncSeq.zipWith3``() =
912+
for la in [ []; [1]; [1;2;3;4;5] ] do
913+
for lb in [ []; [1]; [1;2;3;4;5] ] do
914+
for lc in [ []; [1]; [1;2;3;4;5] ] do
915+
let a = la |> AsyncSeq.ofSeq
916+
let b = lb |> AsyncSeq.ofSeq
917+
let c = lc |> AsyncSeq.ofSeq
918+
let actual = AsyncSeq.zipWith3 (fun a b c -> a + b + c) a b c
919+
let expected = Seq.zip3 la lb lc |> Seq.map (fun (a,b,c) -> a+b+c) |> AsyncSeq.ofSeq
920+
Assert.True(EQ expected actual)
921+
922+
[<Test>]
923+
let ``AsyncSeq.zipWithAsync3``() =
924+
for la in [ []; [1]; [1;2;3;4;5] ] do
925+
for lb in [ []; [1]; [1;2;3;4;5] ] do
926+
for lc in [ []; [1]; [1;2;3;4;5] ] do
927+
let a = la |> AsyncSeq.ofSeq
928+
let b = lb |> AsyncSeq.ofSeq
929+
let c = lc |> AsyncSeq.ofSeq
930+
let actual = AsyncSeq.zipWithAsync3 (fun a b c -> a + b + c |> async.Return) a b c
931+
let expected = Seq.zip3 la lb lc |> Seq.map (fun (a,b,c) -> a+b+c) |> AsyncSeq.ofSeq
932+
Assert.True(EQ expected actual)
933+
898934
[<Test>]
899935
let ``AsyncSeq.append works``() =
900936
for la in [ []; [1]; [1;2;3;4;5] ] do

0 commit comments

Comments
 (0)