Multiple suspend calls in one coroutine still read like ordinary top-to-bottom code.

sequential suspend Suspending functions can compose in sequence: each result feeds the next statement.

Sequential Suspend Calls

bonus
SequentialSuspendCalls.kt
Replay: real traced execution (multi-file project)
import kotlin.coroutines.Continuation
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.coroutines.startCoroutine

suspend fun addBonus(value: Int, bonus: Int): Int {
    return value + bonus
}

suspend fun labelScore(score: Int): String {
    return if (score >= 10) "ready:$score" else "waiting:$score"
}

fun main() {
    val bonus = 3
    var output = "pending"

    val work: suspend () -> String = {
        val first = addBonus(5, bonus)
        val second = addBonus(first, 2)
        labelScore(second)
    }

    work.startCoroutine(object : Continuation<String> {
        override val context = EmptyCoroutineContext

        override fun resumeWith(result: Result<String>) {
            output = result.getOrThrow()
        }
    })

    println("output=$output")
}
import kotlin.coroutines.Continuation
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.coroutines.startCoroutine

suspend fun addBonus(value: Int, bonus: Int): Int {
    return value + bonus
}

suspend fun labelScore(score: Int): String {
    return if (score >= 10) "ready:$score" else "waiting:$score"
}

fun main() {
    val bonus = 0
    var output = "pending"

    val work: suspend () -> String = {
        val first = addBonus(5, bonus)
        val second = addBonus(first, 2)
        labelScore(second)
    }

    work.startCoroutine(object : Continuation<String> {
        override val context = EmptyCoroutineContext

        override fun resumeWith(result: Result<String>) {
            output = result.getOrThrow()
        }
    })

    println("output=$output")
}
import kotlin.coroutines.Continuation
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.coroutines.startCoroutine

suspend fun addBonus(value: Int, bonus: Int): Int {
    return value + bonus
}

suspend fun labelScore(score: Int): String {
    return if (score >= 10) "ready:$score" else "waiting:$score"
}

fun main() {
    val bonus = 7
    var output = "pending"

    val work: suspend () -> String = {
        val first = addBonus(5, bonus)
        val second = addBonus(first, 2)
        labelScore(second)
    }

    work.startCoroutine(object : Continuation<String> {
        override val context = EmptyCoroutineContext

        override fun resumeWith(result: Result<String>) {
            output = result.getOrThrow()
        }
    })

    println("output=$output")
}
  1. bonus ← 3, output ← pending, work ← () -> kotlin.String

    13fun main() {14    val bonus→ 3 = 3 //@bonus=0, 715    var output→ pending = "pending"1617    val work→ () -> kotlin.String: suspend () -> String = {18        val first = addBonus(5, bonus)19        val second = addBonus(first, 2)20        labelScore(second)21    }2223    work() -> kotlin.String.startCoroutine(object : Continuation<String> {24        override val context = EmptyCoroutineContext2526        override fun resumeWith(result: Result<String>) {27            output = result.getOrThrow()28        }29    })
  2. suspend fun addBonus(value: Int, bonus: Int): Int

    pass 1 of 2
    5suspend fun addBonus(value5: Int, bonus3: Int): Int {6    return value5 + bonus37}
  3. val first = addBonus(5, bonus)

    17val work: suspend () -> String = {18    val first = addBonus(5, bonus)19    val second = addBonus(first, 2)20    labelScore(second)
  4. suspend fun addBonus(value: Int, bonus: Int): Int

    pass 2 of 2
    5suspend fun addBonus(value8: Int, bonus2: Int): Int {6    return value8 + bonus27}
  5. val second = addBonus(first, 2)

    18val first = addBonus(5, bonus)19val second = addBonus(first, 2)20labelScore(second)
  6. suspend fun labelScore(score: Int): String

    9suspend fun labelScore(score10: Int): String {10    return if (score10 >= 10) "ready:$score" else "waiting:$score"11}
  7. override fun resumeWith(result: Result<String>)

    23work() -> kotlin.String.startCoroutine(object : Continuation<String> {24    override val context = EmptyCoroutineContext2526    override fun resumeWith(resultSuccess(ready:10): Result<String>) {27        output = resultSuccess(ready:10).getOrThrow()28    }29})
  8. println("output=$output")

    31    println("output=$outputready:10")32}
    outputoutput=ready:10
  1. bonus ← 0, output ← pending, work ← () -> kotlin.String

    13fun main() {14    val bonus→ 0 = 015    var output→ pending = "pending"1617    val work→ () -> kotlin.String: suspend () -> String = {18        val first = addBonus(5, bonus)19        val second = addBonus(first, 2)20        labelScore(second)21    }2223    work() -> kotlin.String.startCoroutine(object : Continuation<String> {24        override val context = EmptyCoroutineContext2526        override fun resumeWith(result: Result<String>) {27            output = result.getOrThrow()28        }29    })
  2. suspend fun addBonus(value: Int, bonus: Int): Int

    pass 1 of 2
    5suspend fun addBonus(value5: Int, bonus0: Int): Int {6    return value5 + bonus07}
  3. val first = addBonus(5, bonus)

    17val work: suspend () -> String = {18    val first = addBonus(5, bonus)19    val second = addBonus(first, 2)20    labelScore(second)
  4. suspend fun addBonus(value: Int, bonus: Int): Int

    pass 2 of 2
    5suspend fun addBonus(value5: Int, bonus2: Int): Int {6    return value5 + bonus27}
  5. val second = addBonus(first, 2)

    18val first = addBonus(5, bonus)19val second = addBonus(first, 2)20labelScore(second)
  6. suspend fun labelScore(score: Int): String

    9suspend fun labelScore(score7: Int): String {10    return if (score7 >= 10) "ready:$score" else "waiting:$score"11}
  7. override fun resumeWith(result: Result<String>)

    23work() -> kotlin.String.startCoroutine(object : Continuation<String> {24    override val context = EmptyCoroutineContext2526    override fun resumeWith(resultSuccess(waiting:7): Result<String>) {27        output = resultSuccess(waiting:7).getOrThrow()28    }29})
  8. println("output=$output")

    31    println("output=$outputwaiting:7")32}
    outputoutput=waiting:7
  1. bonus ← 7, output ← pending, work ← () -> kotlin.String

    13fun main() {14    val bonus→ 7 = 715    var output→ pending = "pending"1617    val work→ () -> kotlin.String: suspend () -> String = {18        val first = addBonus(5, bonus)19        val second = addBonus(first, 2)20        labelScore(second)21    }2223    work() -> kotlin.String.startCoroutine(object : Continuation<String> {24        override val context = EmptyCoroutineContext2526        override fun resumeWith(result: Result<String>) {27            output = result.getOrThrow()28        }29    })
  2. suspend fun addBonus(value: Int, bonus: Int): Int

    pass 1 of 2
    5suspend fun addBonus(value5: Int, bonus7: Int): Int {6    return value5 + bonus77}
  3. val first = addBonus(5, bonus)

    17val work: suspend () -> String = {18    val first = addBonus(5, bonus)19    val second = addBonus(first, 2)20    labelScore(second)
  4. suspend fun addBonus(value: Int, bonus: Int): Int

    pass 2 of 2
    5suspend fun addBonus(value12: Int, bonus2: Int): Int {6    return value12 + bonus27}
  5. val second = addBonus(first, 2)

    18val first = addBonus(5, bonus)19val second = addBonus(first, 2)20labelScore(second)
  6. suspend fun labelScore(score: Int): String

    9suspend fun labelScore(score14: Int): String {10    return if (score14 >= 10) "ready:$score" else "waiting:$score"11}
  7. override fun resumeWith(result: Result<String>)

    23work() -> kotlin.String.startCoroutine(object : Continuation<String> {24    override val context = EmptyCoroutineContext2526    override fun resumeWith(resultSuccess(ready:14): Result<String>) {27        output = resultSuccess(ready:14).getOrThrow()28    }29})
  8. println("output=$output")

    31    println("output=$outputready:14")32}
    outputoutput=ready:14