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

sdmoralesma
Title: Web Development with Clojure, Third Edition - migrations/create not working: p159 When I execute the command: user=> (create-...
New
edruder
I thought that there might be interest in using the book with Rails 6.1 and Ruby 2.7.2. I’ll note what I needed to do differently here. ...
New
Mmm
Hi, build fails on: bracket-lib = “~0.8.1” when running on Mac Mini M1 Rust version 1.5.0: Compiling winit v0.22.2 error[E0308]: mi...
New
nicoatridge
Hi, I have just acquired Michael Fazio’s “Kotlin and Android Development” to learn about game programming for Android. I have a game in p...
New
adamwoolhether
I’m not quite sure what’s going on here, but I’m unable to have to containers successfully complete the Readiness/Liveness checks. I’m im...
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
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
ggerico
I got this error when executing the plot files on macOS Ventura 13.0.1 with Python 3.10.8 and matplotlib 3.6.1: programming_ML/code/03_...
New
dachristenson
I’ve got to the end of Ch. 11, and the app runs, with all tabs displaying what they should – at first. After switching around between St...
New

Other popular topics Top

AstonJ
If it’s a mechanical keyboard, which switches do you have? Would you recommend it? Why? What will your next keyboard be? Pics always w...
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
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
Do the test and post your score :nerd_face: :keyboard: If possible, please add info such as the keyboard you’re using, the layout (Qw...
New
PragmaticBookshelf
Tailwind CSS is an exciting new CSS framework that allows you to design your site by composing simple utility classes to create complex e...
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
PragmaticBookshelf
Build efficient applications that exploit the unique benefits of a pure functional language, learning from an engineer who uses Haskell t...
New
husaindevelop
Inside our android webview app, we are trying to paste the copied content from another app eg (notes) using navigator.clipboard.readtext ...
New
First poster: AstonJ
Jan | Rethink the Computer. Jan turns your computer into an AI machine by running LLMs locally on your computer. It’s a privacy-focus, l...
New
xiji2646-netizen
Woke up to this today: Claude Code’s complete source code exposed via npm source map. Not a snippet. All 512,000 lines. 1,900 TypeScript ...
New

Sub Categories: