Javaru

Javaru

Kotlin Coroutine Confidence: Code does not run (pg 225)

When I run pets/v23 from page 225, I get a quick flash of the “control panel” window, and then the program exits. There is no output in the console other than:

Process finished with exit code 0

Same problem for pets/v24 .

For pets/v25 and pets/v26, I get a single window, and then after the 15 second delay, rather than a second slide show starting, the program exits.

book-kotlin-coroutine-confidence version B3

Marked As Solved

sam-cooper

sam-cooper

Author of Kotlin Coroutine Confidence

Wow, thanks for spotting this! I’m embarrassed I missed it.

Looks like the bug is in the suspending createWindow() function. When we invoke the block() parameter (which, by the way, I’ve renamed to onWindowOpened() after our previous thread), we call window.dispose() immediately afterwards. But the lambda function doesn’t just need to wait for its own code; it also has a CoroutineScope receiver which it can use to launch additional coroutines.

The solution is to wrap block()/onWindowOpened() with its own coroutineScope { … }:

suspend fun createWindow(
  title: String,
  onWindowOpened: suspend CoroutineScope.(JFrame) -> Unit
): Unit = withContext(Dispatchers.Main) {
  val window = JFrame(title)
  window.defaultCloseOperation = JFrame.DISPOSE_ON_CLOSE
  window.size = Dimension(400, 300)
  launch {
    window.addWindowListener(object : WindowAdapter() {
      override fun windowClosed(e: WindowEvent) = this@launch.cancel()
    })
    window.isVisible = true
    try {
      coroutineScope { onWindowOpened(window) }
    } finally {
      window.dispose()
    }
  }
}

This ensures the try block waits for the child coroutines as well as the suspending code. Adding a CoroutineScope receiver to an already-suspending function is a bit of an unusual pattern—it’s something I’d only ever really do in higher-order functions like this one. You can see the same pattern in the launch() and async() functions. It’s really just a convenience thing. Without it, callers would still be able to launch child coroutines by adding a coroutineScope() block inside the lambda code block. In other words, the two working options would be:

  • createWindow(…) { launch { … } } + coroutineScope { onWindowOpened(window) }, or
  • createWindow(…) { coroutineScope { launch { … } } } + onWindowOpened(window)

Evidently I changed my mind halfway through implementing it, and ended up halfway between the two options.

I might add a quick note next to the original createWindow() function explaining this extra coroutineScope(), since it’s a little unusual.

Thank you again for reporting the bug!

Where Next?

Popular Pragmatic Bookshelf topics Top

ianwillie
Hello Brian, I have some problems with running the code in your book. I like the style of the book very much and I have learnt a lot as...
New
jdufour
Hello! On page xix of the preface, it says there is a community forum "… for help if your’re stuck on one of the exercises in this book… ...
New
rmurray10127
Title: Intuitive Python: docker run… denied error (page 2) Attempted to run the docker command in both CLI and Powershell PS C:\Users\r...
New
patoncrispy
I’m new to Rust and am using this book to learn more as well as to feed my interest in game dev. I’ve just finished the flappy dragon exa...
New
brunogirin
When running tox for the first time, I got the following error: ERROR: InterpreterNotFound: python3.10 I realised that I was running ...
New
adamwoolhether
Is there any place where we can discuss the solutions to some of the exercises? I can figure most of them out, but am having trouble with...
New
jonmac
The allprojects block listed on page 245 produces the following error when syncing gradle: “org.gradle.api.GradleScriptException: A prob...
New
s2k
Hi all, currently I wonder how the Tailwind colours work (or don’t work). For example, in app/views/layouts/application.html.erb I have...
New
Henrai
Hi, I’m working on the Chapter 8 of the book. After I add add the point_offset, I’m still able to see acne: In the image above, I re...
New
davetron5000
Hello faithful readers! If you have tried to follow along in the book, you are asked to start up the dev environment via dx/build and ar...
New

Other popular topics Top

Exadra37
Please tell us what is your preferred monitor setup for programming(not gaming) and why you have chosen it. Does your monitor have eye p...
New
PragmaticBookshelf
Design and develop sophisticated 2D games that are as much fun to make as they are to play. From particle effects and pathfinding to soci...
New
DevotionGeo
I know that -t flag is used along with -i flag for getting an interactive shell. But I cannot digest what the man page for docker run com...
New
AstonJ
If you are experiencing Rails console using 100% CPU on your dev machine, then updating your development and test gems might fix the issu...
New
PragmaticBookshelf
Rails 7 completely redefines what it means to produce fantastic user experiences and provides a way to achieve all the benefits of single...
New
AstonJ
Was just curious to see if any were around, found this one: I got 51/100: Not sure if it was meant to buy I am sure at times the b...
New
PragmaticBookshelf
Author Spotlight Rebecca Skinner @RebeccaSkinner Welcome to our latest author spotlight, where we sit down with Rebecca Skinner, auth...
New
PragmaticBookshelf
Programming Ruby is the most complete book on Ruby, covering both the language itself and the standard library as well as commonly used t...
New
New
PragmaticBookshelf
Develop, deploy, and debug BEAM applications using BEAMOps: a new paradigm that focuses on scalability, fault tolerance, and owning each ...
New

Sub Categories: