Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

The concept of "coroutines" is as much about control flow as "subroutines" (function calls and return statements).

But when you have a construct that has their own call stacks, it's a relatively small step to implement lightweight threads with it.

Since doing concurrency happens much more often than any other smart use of coroutines, many people conflate the two.

I sometimes see this confusion in discussions about Kotlin's coroutines. An example of using coroutines that is not about concurrency: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.sequence...



Kotlin's sequence pre-dates co-routines. Mostly what either of those do is just a bit of syntactic sugar on top of call back mechanisms. One of the nice things with Kotlin is the ability to extend existing APIs via extension functions. Which is something the co-routines library uses extensively to be able to provide co-routine implementations on top of existing frameworks on the JVM, in javascript, and in native environments. Same APIs. Same code. Different underlying implementations. I actively use this in some of my multi platform libraries that I use on JVM and in the browser.

The key concept with Kotlin's co-routines is not having to choose between reactive, green threads, or real threads but treating all of those in the same way with a robust set of abstractions. I use co-routines in the browser on top of existing javascript frameworks that return promises. I use them on the JVM with reactive frameworks like flux. And I also use them with some thread pools. Once Loom reaches LTS (next year, I think), I'll probably be configuring some Loom capable co-routine dispatchers as well.

The debate regarding co-routines vs. go-routines seems like it is similar. I think Go can learn a thing or two from Kotlin's co-routines. After all it is mostly built as a library on top of a single language feature: the suspend keyword. I get that not everybody likes colored functions. But then having a lot of leaky abstractions and related complexity on top of go routines is maybe also not ideal.


> Kotlin's sequence pre-dates co-routines.

You misunderstood. The `Sequence` type does predate coroutines. But I meant the `sequence` builder function, which takes a block of suspending code to create a `Sequence`.

The in-order traversal in the article can be translated to Kotlin:

    fun walk(t: Tree?): Sequence<Int> = sequence {
        if (t != null) {
            yieldAll(walk(t.left))
            yield(t.value)
            yieldAll(walk(t.right))
        }
    }
As I have noted above, this is a use of coroutines that has nothing to do with concurrency.


Sequences actually were part of Kotlin 1.0. Co-routines were added later.


> Sequences actually were part of Kotlin 1.0.

But the `sequence` builder function was not. In fact it depends on coroutines.

Could you read my reply before repeating?


In fact python had general coroutines first in yield, which is mostly used for iteration (“generators”) and state machines.

Some frameworks (e.g. twisted) did use them for concurrency, and the core team originally planned something similar, however the ergonomics were not what they wanted (especially when mixing coroutines-for-concurrency and coroutines-for-iteration), so they went for a more specialised design.


> did use them for concurrency

> went for a more specialised design

My impression is that JS evolved similarly - (ab)using generator for concurrency, then specialized async-await as a language feature.


Kinda? But that was a very short cycle, both promises and generators were added to the language in ES6 (though the community had been coalescing around promises — “thenables” — for a while), the first draft for async functions was actually created during the development cycle of ES6, and it was shipped in ES7.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: