Hey, Chris, great to hear from you! I haven't used Kotlin, but I hear good things.
The Kotlin docs say that “Kotlin’s concept of suspending function provides a safer and less error-prone abstraction for asynchronous operations than futures and promises.” That’s a little unsettling, and frankly a dubious claim. Monadic interfaces are extremely well understood and intuitive to most programmers, especially with a little syntactic sugar in the form of comprehensions (as in Python Scala) or async/await syntax. Coroutine APIs are not a good place for language designers to get clever.
The Kotlin developers seem to realize they’re taking a risk, because the core language provides only minimal intrinsics for coroutines [1], leaving the real work to libraries like kotlinx.coroutines. Libraries are easier to change than core language features, and thus leave the door open for backtracking. In Kotlin, yield and await are ordinary functions built atop a one-size-fits-all abstraction called “suspending functions.” My first exposure to coroutines was similar, being built on C’s setjmp and longjmp, but nobody pretended those were easy to use.
In my humble opinion, really low-level features like coroutines belong in the core language, not libraries. The end result of the library approach always feels inferior. As an extreme example, in C++ even tuples [2] and sum types [3] are library features, and using them feels so awkward that C++ would arguably be better off without them.
Of course, my opinion here is entirely academic, as I haven't even used Kotlin. I'd be curious to hear about actual, hands-on experience.
"Java is not very good." - subscribed
Hey Jeff! Great post. What are your thoughts on Kotlin coroutines?
Hey, Chris, great to hear from you! I haven't used Kotlin, but I hear good things.
The Kotlin docs say that “Kotlin’s concept of suspending function provides a safer and less error-prone abstraction for asynchronous operations than futures and promises.” That’s a little unsettling, and frankly a dubious claim. Monadic interfaces are extremely well understood and intuitive to most programmers, especially with a little syntactic sugar in the form of comprehensions (as in Python Scala) or async/await syntax. Coroutine APIs are not a good place for language designers to get clever.
The Kotlin developers seem to realize they’re taking a risk, because the core language provides only minimal intrinsics for coroutines [1], leaving the real work to libraries like kotlinx.coroutines. Libraries are easier to change than core language features, and thus leave the door open for backtracking. In Kotlin, yield and await are ordinary functions built atop a one-size-fits-all abstraction called “suspending functions.” My first exposure to coroutines was similar, being built on C’s setjmp and longjmp, but nobody pretended those were easy to use.
In my humble opinion, really low-level features like coroutines belong in the core language, not libraries. The end result of the library approach always feels inferior. As an extreme example, in C++ even tuples [2] and sum types [3] are library features, and using them feels so awkward that C++ would arguably be better off without them.
Of course, my opinion here is entirely academic, as I haven't even used Kotlin. I'd be curious to hear about actual, hands-on experience.
[1]: https://kotlinlang.org/docs/reference/coroutines-overview.html
[2]: https://en.cppreference.com/w/cpp/utility/tuple
[3]: https://en.cppreference.com/w/cpp/utility/variant