Live data from Hacker News

Coroutines for Go

research.swtch.com

131–140 of 191 posts

Re: Coroutines for Go

#131

what? I'm a Go newb, but isn't this what goroutines and channels get you?

You can build this yourself using goroutines and channels, but adding "native" first-class support for this generator pattern would be easier to use and come with less overhead.

Re: Coroutines for Go

#132

Earlier 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…

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

Re: Coroutines for Go

#133
post #72

Earlier 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.

Not forcing to check errors is akin to what you do in C, and even there compilers complain about this.

Re: Coroutines for Go

#134

Reading 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…

I would have expected that the Go community welcomes a uniform interface for iteration.

Re: Coroutines for Go

#135
post #69

Coroutines 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…

I would prefer to add a `yield` param to functions so it can better interact with the current type system.

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

#136

I 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.

Having coded in go professionally, I disagree. Go abstractions leak in weird and unexpected ways that are surprisingly different to it's C/C++/Java predecessors.

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

#137

Earlier 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.

> 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.

Re: Coroutines for Go

#138
I guess it is great that they are finally paying attentio to programming languages like CLU.

On 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

#139
post #7

I 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

Well, then so is in Java, with the Epsillon “GC”. But not collecting garbage is very different than manual memory management.

Re: Coroutines for Go

#140

It 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.…

[deleted]
Post reply on HN