Hi,
The following code does not compile. It is based on the pipeline example. The problem is in the produceNumbers function. The send call of the producer is embedded in a lambda. This works if the lambda is inline. (see someInlineLamda
). The transaction
call is not inline and gives a compile error (Error:(24, 13) Kotlin: Suspension functions can be called only within coroutine body
).
If I move the transaction code to another inline lambda (see someInlineTransactionLambda
) the lambda needs to be crossinline due to non-local returns but the error remains.
Any ideas on how to resolve this?
import kotlinx.coroutines.experimental.*
import kotlinx.coroutines.experimental.channels.*
import org.jetbrains.exposed.sql.transactions.transaction
inline fun <E> someInlineLambda(x: Int, function: (Int) -> E): Unit {
for (i in 0..1)
function(x)
}
inline fun <E> someInlineTransactionLambda(x: Int, crossinline function: (Int) -> E): Unit {
transaction {
for (i in 0..1) {
function(x)
}
}
}
fun produceNumbers() = produce<Int>(CommonPool) {
var x = 1
while (true) {
someInlineLambda(x) {
send(x++) // OK - inline lambda
}
transaction { // start transaction in exposed land
send(x++) // Error:(24, 13) Kotlin: Suspension functions can be called only within coroutine body
}
someInlineTransactionLamda { // start transaction in exposed land, wrapped in inline lambda
send(x++) // did not work :(
}
}
}
fun square(numbers: ReceiveChannel<Int>) = produce<Int>(CommonPool) {
for (x in numbers) send(x * x)
}
fun main(args: Array<String>) = runBlocking<Unit> {
val numbers = produceNumbers() // produces integers from 1 and on
val squares = square(numbers) // squares integers
for (i in 1..5) println(squares.receive()) // print first five
println("Done!") // we are done
squares.cancel() // need to cancel these coroutines in a larger app
numbers.cancel()
}