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

GilWright
Working through the steps (checking that the Info,plist matches exactly), run the demo game and what appears is grey but does not fill th...
New
simonpeter
When I try the command to create a pair of migration files I get an error. user=> (create-migration "guestbook") Execution error (Ill...
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
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
JohnS
I can’t setup the Rails source code. This happens in a working directory containing multiple (postgres) Rails apps. With: ruby-3.0.0 s...
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
jskubick
I’m under the impression that when the reader gets to page 136 (“View Data with the Database Inspector”), the code SHOULD be able to buil...
New
New
rainforest
Hi, I’ve got a question about the implementation of PubSub when using a Phoenix.Socket.Transport behaviour rather than channels. Before ...
New
a.zampa
@mfazio23 I’m following the indications of the book and arriver ad chapter 10, but the app cannot be compiled due to an error in the Bas...
New

Other popular topics Top

PragmaticBookshelf
Take your Go skills to the next level by learning how to design, develop, and deploy a distributed service. Start from the bare essential...
New
PragmaticBookshelf
Free and open source software is the default choice for the technologies that run our world, and it’s built and maintained by people like...
New
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
AstonJ
You might be thinking we should just ask who’s not using VSCode :joy: however there are some new additions in the space that might give V...
New
AstonJ
Thanks to @foxtrottwist’s and @Tomas’s posts in this thread: Poll: Which code editor do you use? I bought Onivim! :nerd_face: https://on...
New
Help
I am trying to crate a game for the Nintendo switch, I wanted to use Java as I am comfortable with that programming language. Can you use...
New
CommunityNews
A Brief Review of the Minisforum V3 AMD Tablet. Update: I have created an awesome-minisforum-v3 GitHub repository to list information fo...
New
PragmaticBookshelf
Fight complexity and reclaim the original spirit of agility by learning to simplify how you develop software. The result: a more humane a...
New
PragmaticBookshelf
Use advanced functional programming principles, practical Domain-Driven Design techniques, and production-ready Elixir code to build scal...
New

Sub Categories: