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.”
Coroutines for Go
171–180 of 191 posts
Re: Coroutines for Go
#172Earlier 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"
Re: Coroutines for Go
#173Multitasking 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.
Re: Coroutines for Go
#174Multitasking 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.
Re: Coroutines for Go
#175Earlier 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.
Re: Coroutines for Go
#176i'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()); } ...…
@ hashsz s = {
@ h := 53u
@ itersz s, b => {
@ h = (h >> 27 | h Re: Coroutines for Go
#177Earlier 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.
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
#178Earlier 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 :-)
Re: Coroutines for Go
#179Earlier 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…
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
#180i'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
blx r6 @ invoke block argument with byte, then
those responsible for this error have been sackedyears ago, in fact