Live data from Hacker News

Coroutines for Go

research.swtch.com

171–180 of 191 posts

Re: Coroutines for Go

#171
post #113

Earlier quoted context omitted.

More likely they're trying to solve real problems you just haven't hit yet.

The go team has explicitly said this is the past: “You just don’t understand because you’re not at Google’s scale.”

Where have they said this specifically?

Re: Coroutines for Go

#172
post #166

Earlier quoted context omitted.

I wouldn’t confuse HN with “the Go community”. The head of the Go team wrote this post. Will the coro package proposed in the post be added exactly as written? Maybe, but probably not exactly as written. Will something like it be added? I would be willing to bet money on it, yes. How long will it take? I’d say at least a year (release in Go 1.23 in August of 2024), maybe a little longer. I don’t think it could be muc…

Given Go's history, there's a moderately high chance that this will be in a PR and immediately merged within the next few hours. They're a bit bipolar on "listen, wait, debate" vs "we just wrote about a new thing, it's already built and in stdlib but is largely undocumented"

I’ve never seen them do this. What are you talking about?

Re: Coroutines for Go

#173

Multitasking systems gave us processes. But those were too much. So we got threads, which are processes that share an address space, file table, and some other things. The scheduler can switch from one to the other more easily than between processes, and data can be shared between threads without needing serialization. But those were too much. So we got user space threads, which are logical threads of execution that…

I don’t think there’s any further down to go, but there’s probably room to go up to distributed computing. IIRC, some early versions of Go when it was in alpha had channels work across machines.

I think there is. How do you describe data parallelism? coroutine are too big when all your function call are doing the same things, but on a different data (think ISPC, shaders, cuda). There is still one more step in parallelism where coroutine cost to much :-)

Re: Coroutines for Go

#174

Multitasking systems gave us processes. But those were too much. So we got threads, which are processes that share an address space, file table, and some other things. The scheduler can switch from one to the other more easily than between processes, and data can be shared between threads without needing serialization. But those were too much. So we got user space threads, which are logical threads of execution that…

Imagining next step could be something like: "process this collection of task-items as you wish". If you squint, any concurrent execution can be viewed as sequence of tasks (which can also be collections), even if there is only one or two of them.

Something along what Cuda, OpenCL or ISPC do, but integrated to the language.

Re: Coroutines for Go

#175
post #93
post #91

Earlier quoted context omitted.

Goroutines and channels aren't intuitive either. You learn them and become familiar with them over time, at which point they become intuitive __for you__.

actually I get it now. the issue is that OP was giving TWO different examples of use, pulling a single value versus multiple. they should have clarified.

Yes, on review, I should have made two examples instead of combining them. Thanks for persevering through my brevity and reaching understanding :)

Re: Coroutines for Go

#176
post #129

i've been thinking about a closely related feature in a different context: adding block arguments, as in smalltalk or ruby or especially lobster, to a language more like c, with static types and stack allocation i think this would be favorable for (among other things) clu-like iterators and imgui libraries, where you often want to do something like submenu("&Edit") { command("&Cut") { clip_cut(getSelection()); } ...…

corrected, tested, and commented version of the above example code

            @ hashsz s = {
            @   h := 53u
            @   itersz s, b => {
            @     h = (h >> 27 | h 

Re: Coroutines for Go

#177
post #81

Earlier quoted context omitted.

I think more idiomatic go for the first case would be: getNext := iterableThing.Iterator() for next, ok := getNext(); ok; next, ok = getNext() { ... } Which, yeah, the range cleans it up a bit, but it's not doing quite as much work as you're implying.

Don't forget that the important bit in Go is readability of the code. To me the range form is much easier to reason about than this for loop.

If we're going for readability instead of trying to stick to the case presented above, I'd go with:

    for i.HasNext() {
        current := i.GetNext()
        ...
    }
And just mutate the internal state of the struct. Probably throw it behind some sort of interface like:

    type Iterator[T any] interface { // feel free to strip out the generic
        HasNext() bool               // if you really only have one type
        GetNext() T                  // you do this with
    }
I think this still loses to ranging over a function, but I still think it should be compared to what you can do with the current language as opposed to what was originally posted.

Re: Coroutines for Go

#178

Earlier quoted context omitted.

I don’t think there’s any further down to go, but there’s probably room to go up to distributed computing. IIRC, some early versions of Go when it was in alpha had channels work across machines.

I think there is. How do you describe data parallelism? coroutine are too big when all your function call are doing the same things, but on a different data (think ISPC, shaders, cuda). There is still one more step in parallelism where coroutine cost to much :-)

Good point. SIMD routines!

Re: Coroutines for Go

#179

Earlier quoted context omitted.

It's not just about performance, but also safety and ergonomics. Since true coroutines[1] offer predictable scheduling, their behavior with regards to data races and deadlocks is also more predictable. If programmers try to manually implement iterators, generators and interleaved state machines with their own goroutines and channels, it's not just performance that suffers - there is too much room for error. [1] I'm u…

> I'm using the qualifier "true" here, since many modern languages (such as Python, Kotlin) use the term "coroutines" for something that is more like Go's Goroutines than Lua's coroutines. Python has both true (ish) coroutines (or at least coroutines which are entirely user controllable), which it mostly uses for iteration, and the concurrency specialised “async”. Initially the goal was to reuse “yield” for concurren…

It's almost true. Python calls its "almost true" coroutines "generators", while the implicitly scheduled, async I/O-oriented coroutines are just called "coroutines".

I understand that the historical reasons for that ("generators" originally only supported "yield" and a separate async/await design with implicit scheduling seemed more ergonomic). But that doesn't remove the confusion.

But Python's generators are still fully "true" coroutines. Russ makes the distinction between coroutines and generators based on whether as "Generators provide less power than coroutines, because only the top-most frame in the coroutine is allowed to yield. ". I think this is a bad definition, as generators can clearly "pass" the yielding power to other generators with "yield from", and Russ talks about this feature in the same post. Generators require more ceremony, but I don't think they are "less powerful" in any meaningful way .

Roberto Ierusalimschy, the creator of Lua, and Ana Lucia de Moura proposed the distinction between stackful and stackless coroutines[1]. Their paper revived coroutines as a research subject and had a lasting impact on coroutine-related terminology. Ierusalimschy and Moura made the distinction between "Stackful" coroutines and "non-stackful coroutines" (the term "stackless coroutines" stuck later on, but they did not use it), where Stackful coroutines like Lua's coroutines can "suspend their execution from within nested functions". They also made the same allusion to power that Russ does: "powerful enough to constitute a general control abstraction; in particular, they can- not be used as a concurrent construct".

I think both Ierusalimschy and de Moura are onto something when they call generators "limited", but they are just incorrect when they say that "but are not powerful enough to constitute a general control abstraction; in particular, they cannot be used as a concurrent construct". Early Node.js libraries and frameworks such as "co" and "koa"[2] should count as a proof that you can very much use generators as a concurrency construct. Generators have all the power that is necessary for dealing with normal concurrency cases, although they don't have the best ergonomics.

But there is another distinction where "generators" are not the same as Lua coroutines, and clearly lack some expressive power (even though this power is NOT a necessary condition for implementing full-fledged concurrency). Lua allows coroutines to communicate bidrectionally: yield() can pass a value back the coroutine caller, which is returned from resume() - but when the coroutine caller calls resume() again they can pass an argument which will be returned from yield(). Generators are unidirectional: they only allow you to pass a value to yield(), but not to resume().

[1] http://www.inf.puc-rio.br/~roberto/docs/MCC15-04.pdf [2] https://news.ycombinator.com/item?id=6933358

Re: Coroutines for Go

#180
post #176
post #129

i've been thinking about a closely related feature in a different context: adding block arguments, as in smalltalk or ruby or especially lobster, to a language more like c, with static types and stack allocation i think this would be favorable for (among other things) clu-like iterators and imgui libraries, where you often want to do something like submenu("&Edit") { command("&Cut") { clip_cut(getSelection()); } ...…

corrected, tested, and commented version of the above example code @ hashsz s = { @ h := 53u @ itersz s, b => { @ h = (h >> 27 | h

fe de ratas, the above should read

            blx  r6                 @ invoke block argument with byte, then
those responsible for this error have been sacked

years ago, in fact

Post reply on HN