Concurrency 101

After my naive attempt at defining an array of async let bindings:

let fv: [() async -> Int]  = [f, g, h]
let uv: [async Int] = [] // <--- not possible

for f in fv {
    async let u = f ()
    uv.append (u)
}

for u in uv {
    await print (u)
}

I asked the question "Will array of async values be possible?" here .

The answer was not a definite no.

However, @crontab has a utility (Zip) in his personal library, which provides a good workable solution.

It uses a task group underneath, which simplifies the nesting of the task groups, resulting in clean looking code.

@main
enum AsyncZip {
    static func main () async throws {
        @Sendable func n () -> Int {
            let v = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37]
            return v [Int.random (in: 0..<v.count)]
        }

        @Sendable func f () async throws -> Int {n () + 1}

        let u = Zip (actions: [f, f, f])
        try await print (u.result)
        
        @Sendable func p () async throws -> [Int] {
            let u = Zip (actions: [f, f, f, f, f])
            return try await u.result
        }
        
        var v = Zip <[Int]> ()
        v.add (p)
        v.add (p)
        v.add (p)
        try await print (v.result)
    }
}

Possible output:

[18, 30, 30]
[[3, 32, 38, 24, 8], [8, 3, 30, 12, 8], [38, 6, 24, 3, 38]]