what? I'm a Go newb, but isn't this what goroutines and channels get you?
Coroutines for Go
131–140 of 191 posts
Re: Coroutines for Go
#132Earlier quoted context omitted.
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 envi…
> 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 = sequence { if (t != null) { yieldAll(walk(t.left)) yield(t.value) yieldAll(walk(t.right)) } } As I have not…
Re: Coroutines for Go
#133Earlier quoted context omitted.
In practice the difference would be closer to: getNext := iterableThing.Iterator() for { next, ok := getNext() if !ok { break } ... } vs. for next := range iterableThing.Iterator() { ... } One advantage is that it's slightly shorter, which matters for very common patterns--people complain about `err != nil` after all. Another advantage is there isn't another variable for everyone to name differently. Another advantag…
> complain about `err != nil` after all Not to nitpick this specifically but as a generic reminder not all complaints are worthy of shifting the trajectory of a massively popular programming language. Balancing "worthy" and "unworthy" changes is really hard both in the community and discussions like this one. I don't envy the teams that have to do it.
Re: Coroutines for Go
#134Reading the comments makes me feel bittersweet. - Many people consider coroutines and green threads to be more or less the same thing, when they both have their pros and cons. - The fact that the omission of iterators is even acceptable in the Go community saddens me. They seem to deliberately refuse any feature that might make the language even slightly more complex, in the name of simplicity. But hey, at least they…
Re: Coroutines for Go
#135Coroutines are one thing that i'd probably prefer language support for rather than a library. x := co func(){ var z int for { z++ yield z } } y := x() for y := range x { ... } or something to that effect. It's cool that it can be done at all in pure go, and I can see the appeal of having a standard library package for it with an optimized runtime instead of complecting the language specification. After all, if it's p…
This means that for a function to yield, it needs to have the so called `yield` param and you can only yield inside a yield function functions with the same yield signature or does not contain a signature at all.
So the example would be rewritten into something like:
x := func(:z int) {
for {
z++
:- z
}
}
for y := range x() {
...
}
The : adds the yield signature and :Functions that only yield a value `X` would just have the `: X` or `: name X`.
To accept a value of type `Y` in the resume the signature would change to `:[Y] X` or `:[Y] name X`.Accepting is weak, so if something expects a yielding function that resumes with Y and yield X, yielding functions that only yield X without a resume should also be accepted.
Consider the following code example:
func filter[T comparable](it func(:T), f func(T) bool, :T) {
for v := range it {
if f(v) { :- v }
}
}
func map[T](arr []T, :T) {
for _, v := range arr {
:- v
}
}
for v := range filter(map({1, 2, 3}), func(x) { return x
Special functions in a co package could give resume and New functionality to keep the go style.A basic counter could be written like this:
func counter(:[bool]c int) {
for {
if ! :- c { break }
c += 1
}
}
A func that counts twice could be as simple as: func countTwice(:[bool]c int) {
count()
count()
}
To interact with the resume value the range syntax could be expanded to something like: for c := range count() {
if c > 10 { -: false }
-: true
print(c)
}
Range would resume with a default zero value if the range does not pass a value to -:.Re: Coroutines for Go
#136I don’t think Coroutines would fit in with Go. There is a huge emphasis on simplicity. Coroutines add a massive amount of complexity. In addition, goroutines provide the best parts of Coroutines - cheap, easy to use, non-blocking operations - without a lot of the pain pints such as “coloring” or functions and issues with using things like mutexes. Just the question of whether one should use a goroutine or a coroutine…
There are plenty of complicated things in Go, IMHO where it shines best is judiciously providing incredibly nice interfaces atop the complicated things.
Goroutines were kind of the raison detre' for using go. But using them wasn't simple, and instead often goroutines brought their own issues. See here:
https://songlh.github.io/paper/go-study.pdf
Often a programming language takes a first guess at the problems they want to solve, and often get them wrong. C++ is probably the most notable language in this category here.
That said, I do appreciate an attempt to improve programming languages even if it undermines the primary feature of the language itself.
Re: Coroutines for Go
#137Earlier quoted context omitted.
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 Ko…
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.
> 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.
Re: Coroutines for Go
#138On the other side, given my experience with .NET and C++ co-routines, and Active Objects (in Symbian C++ and Active Oberon) not sure if this is really something to add to Go.
Even the .NET team has acknowledged at this year's BUILD, that if they could go back in time having the runtime handle them Go-style would probably been a better decision, given how many developers keep having issues understanding async/await.
Re: Coroutines for Go
#139I thought that the entire point of green threads was so that I didn't have to use something like Python's `yield` keyword to get nice, cooperative-style scheduling. I thought go's `insert resumes at call points and other specific places` design decision was a very nice compromise. This is allowing access to more and more of the metal. At what point are we just recreating Zig here? What's next? An optional garbage col…
Garbage collector in Go is optional. You can switch off garbage collection by setting the environment variable GOGC=off. More info about GOGC: https://dave.cheney.net/tag/gogc
Re: Coroutines for Go
#140It looks like a lot of people are missing the point here. Yes a coroutine library would be a worse/more cumbersome way to do concurrency than the go keyword. The use case motivating all the complexity is function iterators, where `range` can be used on functions of type `func() (T, bool)`. That has been discussed in the Go community for a long time, and the semantics would be intuitive/obvious to most Go programmers.…