Void as an associated type?

Say I wanted to add asynchronous versions of slow, blocking methods in lots of places, and (for some reason) I decided to do:

protocol Awaitable<Arg, Result> {
    
    associatedtype Arg
    associatedtype Result
    
    var slowFunction: (Input) -> Output { get }
}

extension Awaitable {

    func result(from x:Arg) async -> Result {
        
       return await Task() { slowFunction(x) }.value
    }
}

As well as being a lot more work than just adding a one-liner for every case, I couldn't use this to generate an AsyncSequence, because I'd need to write:

extension SlowCoach : Awaitable {

    func generator() -> Value {
        return // something hard //
    }
    
    var slowFunction: () -> Value { generator }
    
    typealias Input = // ??? //
    typealias Output = Value
}

I was just musing, really, and wondered if there actually is a way to specify Void as an associated type? Or can there never be a reasonable use case for it, for some reason? Just wondering...

1 Like

To satisfy the protocol, you'd need to write:

    var slowFunction: (()) -> Value = { _ in generator() }
1 Like

Void not carrying over like you're expecting leads to the necessity to do this kind of thing:

Thanks for that. So when it calls slowFunction(x), is the x a closure? Sorry, I'm just trying to understand what Void actually means in Swift.

x can only be (), which is the only value of type Void, aka (). In Swift, Void is a type alias for (), the empty tuple type.

Got it. Thanks. And thanks to Jessy, too - very helpful examples. Think it was the Void being on the other side that got me confused. Cheers

1 Like