ceving
ceving

Reputation: 23871

How to return a suspend function, which accepts an argument?

All of the following examples require a mutex variable.

val mutex = Mutex()

If I have an non-suspend function, I can use it create a synchronzied suspend function:

fun action0 () {}

suspend fun synchronizedAction0 () {
    mutex.withLock {
        action0 ()
    }
}

The same applies to functions with arguments:

fun action1 (x: T) {}

suspend fun synchronizedAction1 (x: T) {
    mutex.withLock {
        action1 (x)
    }
}

If I have more than one non-suspend function, I want to convert into synchronized versions, I can write a non-suspend function, which takes another non-suspend function and converts it into a suspend function.

fun synchronize (action0: () -> Unit): suspend () -> Unit {
    return suspend {
        mutex.withLock {
            action0 ()
        }
    }
}

But how to do it for an action, which requires an argument?

I tried this, but it does not compile:

fun synchronize (action1: (T) -> Unit): suspend (T) -> Unit {
    return suspend { x ->
        mutex.withLock {
            action1 (x)
        }
    }
}

The error is, that the compiler can not infer the type of parameter x. I think it is obvious, it is T. How can I tell Kotlin?

I tried this, but it does not compile either.

fun synchronize (action1: (T) -> Unit): suspend (T) -> Unit {
    return suspend fun (x: T) {
        mutex.withLock {
            action1 (x)
        }
    }
}

What is the right syntax?

Upvotes: 0

Views: 170

Answers (1)

broot
broot

Reputation: 28462

First of all, we need to define T as a type parameter for the synchronize() function. Then we don't really have to specify suspend or argument types for the lambda - they will be automatically inferred by the compiler:

fun <T> synchronize (action1: (T) -> Unit): suspend (T) -> Unit {
    return { x ->
        mutex.withLock {
            action1 (x)
        }
    }
}

Upvotes: 2

Related Questions