There's also the additional objection that this doesn't play well with break/return - if the iterator needs to do some cleanup (say, closing a file or something). IMO, these days, just use bufio.Scanner-like iterators or just a channel+context, if syntax is that important to you. But personally I don't see the point of introducing a custom iterator concept just to *occasionally* save one or two lines of code.
On Mon, Oct 22, 2018 at 7:16 PM Eric S. Raymond <e...@thyrsus.com> wrote: > David Anderson <d...@natulte.net>: > > https://github.com/golang/go/issues/13027 is a past proposal to allow > the > > `range` operation to work on arbitrary types (although it was originally > > proposed as a narrow enhancement on container/list only). Didn't get very > > far, but sprinkled in the bug are some of the objections a new proposal > > would want to address. > > Read it. Not thought through very well, alas. Rightly rejected. > > > The big one for me personally is the argument for readability: currently, > > Go code doesn't contain surprising execution: if there's not a function > > call, you can reasonably expect that there's no hidden computation > > happening. Python-style iterators and generators specifically go against > > that, in that a simple looking range statement might run arbitrarily > > complex code between loop iterations, rather than just increment a > pointer. > > That is a reasonable objection. But there is potentially a *much* > simpler way to specify an iterator that actually *uses* a function > call, properly cluing the reader in that something function-call-like > is going on. And doesn't require a special iterator construct tied > to classes, meeting Griesemer's objection. > > In my real-world case, I want an iterator so I can walk through a list > of hundreds of thousands of items selecting those of interest without > having to construct the entire list of selectees. I'm mulling over a > couple of alternative variations, but the core idea is to give range > new semantics when it's passed an expression of *function* type > > Suppose you see this: > > for i, commit:= range IteratorFactory(MyStupidlyLongEventList, "commits") { > DoStuffWith(commit) > } > > The concept is that the first thing the loop does is call > IteratorFactory(), > which returns not a list but a *closure*. The loop then evaluates the > closure > repeatedly, binding its return value to commit and running the loop body, > until > the closure return tells the loop to terminate, > > This meets the discoverability objection. The function call is your > clue that to understand he loop you need to look at the return value of > IteractorFactory, which could have been a list or map or channel before > my proposal and could after it be a closure. > > (I think it's a little oversimplifying to claim that the current semantics > is as simple as a pointer bump, especially with respect to channels.) > > The detail in which the devil lurks is how the closure returns a stop > value. > There are a couple of different ways this could work; I'll write an RFE > once I figure out which is the Right Thing. > -- > <a href="http://www.catb.org/~esr/">Eric S. Raymond</a> > > My work is funded by the Internet Civil Engineering Institute: > https://icei.org > Please visit their site and donate: the civilization you save might be > your own. > > > -- > You received this message because you are subscribed to the Google Groups > "golang-nuts" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to golang-nuts+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.