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

jon
Some minor things in the paper edition that says “3 2020” on the title page verso, not mentioned in the book’s errata online: p. 186 But...
New
lirux
Hi Jamis, I think there’s an issue with a test on chapter 6. I own the ebook, version P1.0 Feb. 2019. This test doesn’t pass for me: ...
New
mikecargal
Title: Hands-on Rust: question about get_component (page 295) (feel free to respond. “You dug you’re own hole… good luck”) I have somet...
New
raul
Page 28: It implements io.ReaderAt on the store type. Sorry if it’s a dumb question but was the io.ReaderAt supposed to be io.ReadAt? ...
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
jeremyhuiskamp
Title: Web Development with Clojure, Third Edition, vB17.0 (p9) The create table guestbook syntax suggested doesn’t seem to be accepted ...
New
jskubick
I think I might have found a problem involving SwitchCompat, thumbTint, and trackTint. As entered, the SwitchCompat changes color to hol...
New
digitalbias
Title: Build a Weather Station with Elixir and Nerves: Problem connecting to Postgres with Grafana on (page 64) If you follow the defau...
New
dsmith42
Hey there, I’m enjoying this book and have learned a few things alredayd. However, in Chapter 4 I believe we are meant to see the “>...
New
AufHe
I’m a newbie to Rails 7 and have hit an issue with the bin/Dev script mentioned on pages 112-113. Iteration A1 - Seeing the list of prod...
New

Other popular topics Top

PragmaticBookshelf
Ruby, Io, Prolog, Scala, Erlang, Clojure, Haskell. With Seven Languages in Seven Weeks, by Bruce A. Tate, you’ll go beyond the syntax—and...
New
DevotionGeo
I know that these benchmarks might not be the exact picture of real-world scenario, but still I expect a Rust web framework performing a ...
New
siddhant3030
I’m thinking of buying a monitor that I can rotate to use as a vertical monitor? Also, I want to know if someone is using it for program...
New
PragmaticBookshelf
From finance to artificial intelligence, genetic algorithms are a powerful tool with a wide array of applications. But you don't need an ...
New
AstonJ
I’ve been hearing quite a lot of comments relating to the sound of a keyboard, with one of the most desirable of these called ‘thock’, he...
New
rustkas
Intensively researching Erlang books and additional resources on it, I have found that the topic of using Regular Expressions is either c...
New
AstonJ
Saw this on TikTok of all places! :lol: Anyone heard of them before? Lite:
New
New
sir.laksmana_wenk
I’m able to do the “artistic” part of game-development; character designing/modeling, music, environment modeling, etc. However, I don’t...
New
Fl4m3Ph03n1x
Background Lately I am in a quest to find a good quality TTS ai generation tool to run locally in order to create audio for some videos I...
New

Sub Categories: