5 ms·
It would be nice if the proposal defined the semantics of getting single item from the iterator (or detecting that it is out of items) and exposed an api for th
by anonymoushn 3y ago
It would be nice if the proposal defined the semantics of getting single item from the iterator (or detecting that it is out of items) and exposed an api for this, then defined the behavior of range as equivalent to some pattern using these primitives.
As is the proposal says "there should be some coro.Pull type thing" which is a bit terse and says nothing about whether the implementation of coro.Pull will be fast or whether it will be built on range + channels
- znkr 3y agohttps://research.swtch.com/coro https://research.swtch.com/coro
- anonymoushn 3y agoThis does not contain anything about the proposed implementation of Pull, of course.
- Groxx 3y agoWouldn't this be the implementation? func Pull[V any](push func(yield func(V) bool)) (pull func() (V, bool), stop func()) { ... // snipped because it's big }
- anonymoushn 3y agoThat is an implementation in terms of primitives that are not in the proposal.
- Groxx 3y agoI don't believe so - the post is pretty much all about how you can do this right now in normal Go code. And e.g. a bit after that is a link to the "full code" which is runnable: https://go.dev/play/p/hniFxnbXTgH https://go.dev/play/p/hniFxnbXTgH Possibly you're interpreting yield as a new keyword? It's just an argument to Pull. The only not-(currently-)available-in-Go stuff that I can recall from the post is the performance optimization at the very end.
- anonymoushn 3y agoYou can read the proposal here: https://github.com/golang/go/issues/61405 https://github.com/golang/go/issues/61405. It is linked in the first paragraph of TFA. Yes, I know you can build a 100x-too-slow version of this on top of channels, but that's not the proposed extension to the language.
- Groxx 3y agoI suspect getting a single item out will be that you just make a func next[T](i iterfunc[T]) T { var item T i(func(it T) bool){ item = it return true // likely }) return item } and use it. Semantics should be the same as ranging would desugar to (since that's all this is), though the variable arity will be slightly annoying of course.
- anonymoushn 3y agoSure, and that should be somewhere in the very long posts about this or in the very long github issue.
- assbuttbuttass 3y agoI don't think it's so easy. An iterfunc doesn't store any state explicitly, so each time you call i it restarts from the beginning
- Groxx 3y agoAah, yes, that's an excellent point. Thanks! That does complicate things a lot more. Quite a lot more, as it essentially means you can only consume from iterators you create... which sorta defeats the purpose of iterators as a value, and degrades them almost completely to just a `range` helper. --- edit from https://github.com/golang/go/issues/61405 https://github.com/golang/go/issues/61405 >To convert one of these functions to a "next-based" or "pull-based" iterator, we plan to add a function to the standard library that runs the yield-based ("push-based") iterator in a coroutine, along the lines of the coro.Pull function in my recent blog post. that's... an option I guess. Unless the runtime special-cases this coroutine though it seems like it'll probably have non-trivial performance cost, roughly equivalent to the channel + goroutine equivalents people sometimes build now. Which seems... not great. Bad enough that anyone even slightly performance-sensitive will probably avoid it. (his coro post also mentions a proposed runtime change to improve the performance, but afaik previous attempts to get this kind of change into the language haven't worked out reliably, and you can't trust callers to be single-threaded)