Re: [go-nuts] Failed iterator proposals?
On Fri, Oct 26, 2018 at 6:04 AM robert engels wrote: > Barring that, I don’t see how > > for(i:=c.Iterator();i.HasNext();) { > v := i.Next() > } > > is that much more difficult to use Yes, an iterator with a Next method (possibly with another name) is the idiomatic way to present database-y things when you don't necessarily want to pull the whole result set into memory. David Anderson already mentioned the bufio.Scanner type. There's also: https://golang.org/pkg/database/sql/#example_Rows https://golang.org/pkg/debug/dwarf/#Reader.Next https://cloud.google.com/appengine/docs/standard/go/datastore/reference#hdr-Queries https://godoc.org/github.com/golang/leveldb/db -- 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.
Re: [go-nuts] Failed iterator proposals?
On Thu, Oct 25, 2018 at 1:53 PM Eric S. Raymond wrote: > > robert engels : > > Wouldn’t you normally pass a consumer or collector function into the > > interator code? Then you only write the iterator once, and it is hidden. > > I'll look into that approach. There might be a readability issue there. You can extend that to implement something similar to Java streams, like: type Stream func() (Item,bool) func (s Stream) Filter(predicate func(Item) bool) Stream {...} func (s Stream) ForEach(f func(Item) bool) {...} func Iterator([]Item) Stream {...} Iterator(bigArray). Filter(func(item Item) bool { ... }). ForEach(func(item Item) bool { ... }) You could probably come up with different Iterator() functions if you have multiple ways of iterating through your data structure. > > > Similar to how the sync.Map.Range() works. > > > > Barring that, I don’t see how > > > > for(i:=c.Iterator();i.HasNext();) { > > v := i.Next() > > } > > > > is that much more difficult to use - especially since you state it is a > > custom iteration anyway? > > I don't like the eyeball friction. > > I write for long timescales. Someone other than me will have to be able to > maintain this code someday. > -- > http://www.catb.org/~esr/";>Eric S. Raymond > > 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.
Re: [go-nuts] Failed iterator proposals?
The design has been used in Java for many, many, years… pretty sure most developers understand it. In fact, before Java had generics and the Iterable interface it was the only game in town if you wanted type safety - and the Go code is even more concise do to type inference. > On Oct 25, 2018, at 2:52 PM, Eric S. Raymond wrote: > > robert engels : >> Wouldn’t you normally pass a consumer or collector function into the >> interator code? Then you only write the iterator once, and it is hidden. > > I'll look into that approach. There might be a readability issue there. > >> Similar to how the sync.Map.Range() works. >> >> Barring that, I don’t see how >> >> for(i:=c.Iterator();i.HasNext();) { >> v := i.Next() >> } >> >> is that much more difficult to use - especially since you state it is a >> custom iteration anyway? > > I don't like the eyeball friction. > > I write for long timescales. Someone other than me will have to be able to > maintain this code someday. > -- > http://www.catb.org/~esr/";>Eric S. Raymond > > 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.
Re: [go-nuts] Failed iterator proposals?
robert engels : > Wouldn’t you normally pass a consumer or collector function into the > interator code? Then you only write the iterator once, and it is hidden. I'll look into that approach. There might be a readability issue there. > Similar to how the sync.Map.Range() works. > > Barring that, I don’t see how > > for(i:=c.Iterator();i.HasNext();) { > v := i.Next() > } > > is that much more difficult to use - especially since you state it is a > custom iteration anyway? I don't like the eyeball friction. I write for long timescales. Someone other than me will have to be able to maintain this code someday. -- http://www.catb.org/~esr/";>Eric S. Raymond 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.
Re: [go-nuts] Failed iterator proposals?
Wouldn’t you normally pass a consumer or collector function into the interator code? Then you only write the iterator once, and it is hidden. Similar to how the sync.Map.Range() works. Barring that, I don’t see how for(i:=c.Iterator();i.HasNext();) { v := i.Next() } is that much more difficult to use - especially since you state it is a custom iteration anyway? > On Oct 25, 2018, at 1:51 PM, Eric S. Raymond wrote: > > Jan Mercl <0xj...@gmail.com>: >> The 'obvious' way is not something I'd consider. The 'concise' way works >> today, provided iterator function returns a slice or a map. > > Yes, but returning a slice (eager evaluation) is exactly what I want to avoid. > > The context: the repository where my Python version hit a performance wall > has 259K events in it. It's the history of the GNU Compiler Collection. > > A very common thing for my code to need to do is to iterate over all events > of a > certain type - most often Commits, representing changes to filesets - so that > it can select a subset to be passed to mutator code. > > I want to be able to say "for i, c := range repo.commits() {do_something(c)}", > but without iterators this requires constructing an intermediate slice of > commits only inside the commits() fuction, then passing that back to the > range loop. > > That's annoying. Often I'm only going to use a small handful of those > pointers. > With eager list evaluation, Go's memory manager gets hammered as though I were > going to use the entire list every time. > > Remember that I'm doing this translation to improve performance. I'm > unavoidably > going to do a lot of allocations when deserializing the repisitory into its > in-memory attributed-graph form, but after that I really want to keep heap > churn to the bare mimimum required by the surgical operations. > -- > http://www.catb.org/~esr/";>Eric S. Raymond > > 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.
Re: [go-nuts] Failed iterator proposals?
Jan Mercl <0xj...@gmail.com>: > The 'obvious' way is not something I'd consider. The 'concise' way works > today, provided iterator function returns a slice or a map. Yes, but returning a slice (eager evaluation) is exactly what I want to avoid. The context: the repository where my Python version hit a performance wall has 259K events in it. It's the history of the GNU Compiler Collection. A very common thing for my code to need to do is to iterate over all events of a certain type - most often Commits, representing changes to filesets - so that it can select a subset to be passed to mutator code. I want to be able to say "for i, c := range repo.commits() {do_something(c)}", but without iterators this requires constructing an intermediate slice of commits only inside the commits() fuction, then passing that back to the range loop. That's annoying. Often I'm only going to use a small handful of those pointers. With eager list evaluation, Go's memory manager gets hammered as though I were going to use the entire list every time. Remember that I'm doing this translation to improve performance. I'm unavoidably going to do a lot of allocations when deserializing the repisitory into its in-memory attributed-graph form, but after that I really want to keep heap churn to the bare mimimum required by the surgical operations. -- http://www.catb.org/~esr/";>Eric S. Raymond 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.
Re: [go-nuts] Failed iterator proposals?
Axel Wagner : > So, how many such loops are there? In my code? 82, for a first approximation. there might be some I'm missing. -- http://www.catb.org/~esr/";>Eric S. Raymond 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.
Re: [go-nuts] Failed iterator proposals?
On Wed, Oct 24, 2018 at 2:35 PM Eric S. Raymond wrote: > Axel Wagner : > > The key term was "occasionally". I don't know how often "iterators that > > don't need any error handling or cleanup" comes up, but I'd imagine it to > > be pretty rare. In Python, for example, this might be a bit different, > > because the iterator can just throw. And if you actually don't need error > > handling or cleanup, using a channel seems fine (and on par with any > > generic iteration construct in terms of LOC). > > > > If saving LOC is the goal (TBH I contest that all LOC are created equal > in > > this regard) there are much lower hanging fruit. > > My "low-hanging fruit" is the real problems I'm encountering > tranlating 14KLOC of algorithmically dense Python that operates on > data sets gigabytes wide (translation now 70% complete). I think > that's a pretty good road test. > So, how many such loops are there? Because if I, for example, grep through all of golang.org/x that I have on my machine right now, less than 2% of lines contain "for", so I'd say 2% already provides an extremely generous upper bound of the percentage of SLOC this would save for average Go code. It's probably a *lot* lower than that as I'd say the vast majority of loops won't benefit at all from custom iterators. But even 1% is IMO still not a very important amount of saved SLOC, especially if the saved SLOC are obvious and unlikely to hide bugs. You shouldn't assume I don't have ideas about error handling and cleanup > just bceause you haven't seen them yet. I did nothing of the sort. I just spoke from my own experience about how common that is. Anyway. Feel free to spend more time on this as you see fit. It's yours to spend, after all. They's be in a complete RFE. > -- > http://www.catb.org/~esr/";>Eric S. Raymond > > 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.
Re: [go-nuts] Failed iterator proposals?
On Mon, Oct 22, 2018 at 2:41 AM Eric Raymond wrote: > There's an obvious, clumsy way to do this by having a factory pass back a stateful iterator object: > > for iterator := IteratorFactory(selector); iterator.Continue();iterator.Next(){ >DoSomethingWith(iterator.Value()) > } > > What one would really like to be able to do, though, is much more concise: > > for i, v := range iteratorFunction() { >DoSomethingWith(i, v) > } > The 'obvious' way is not something I'd consider. The 'concise' way works today, provided iterator function returns a slice or a map. I'd probably write something like for item := someSetup(selector); item.Next(); { DoSomethingWith(item) } Item type can be whatever is needed, like `struct{i, v int}` or something much more complex. I don't think that this calls for a language change. -- -j -- 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.
Re: [go-nuts] Failed iterator proposals?
Axel Wagner : > The key term was "occasionally". I don't know how often "iterators that > don't need any error handling or cleanup" comes up, but I'd imagine it to > be pretty rare. In Python, for example, this might be a bit different, > because the iterator can just throw. And if you actually don't need error > handling or cleanup, using a channel seems fine (and on par with any > generic iteration construct in terms of LOC). > > If saving LOC is the goal (TBH I contest that all LOC are created equal in > this regard) there are much lower hanging fruit. My "low-hanging fruit" is the real problems I'm encountering tranlating 14KLOC of algorithmically dense Python that operates on data sets gigabytes wide (translation now 70% complete). I think that's a pretty good road test. You shouldn't assume I don't have ideas about error handling and cleanup just bceause you haven't seen them yet. They's be in a complete RFE. -- http://www.catb.org/~esr/";>Eric S. Raymond 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.
Re: [go-nuts] Failed iterator proposals?
On Mon, Oct 22, 2018 at 10:41 PM Eric S. Raymond wrote: > Axel Wagner : > > But personally I don't see the point of introducing a custom iterator > concept > > just to *occasionally* save one or two lines of code. > > Don't despise saving lines of code. There's a well-known law the name of > which I've forgotten that defect rates per KLOC are rougly constant across > languages. Accordingly, what you're really doing when you enable your > language > to do more in fewer LOC is lowering your defect load. > > Thart's not really how I think of it, though. I think in terms of reducing > eyeball friction. Always a virtue when you're programming at scale. > > These might be the same issue, actually. > The key term was "occasionally". I don't know how often "iterators that don't need any error handling or cleanup" comes up, but I'd imagine it to be pretty rare. In Python, for example, this might be a bit different, because the iterator can just throw. And if you actually don't need error handling or cleanup, using a channel seems fine (and on par with any generic iteration construct in terms of LOC). If saving LOC is the goal (TBH I contest that all LOC are created equal in this regard) there are much lower hanging fruit. > -- > http://www.catb.org/~esr/";>Eric S. Raymond > > 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.
Re: [go-nuts] Failed iterator proposals?
Quoting robert engels (2018-10-22 16:01:18) > I am sure it has been discussed, but why the aversion to using < > in > type declarations? I guess I just don’t understand using bracketing > notations that are already used for something else. This was mentioned in the draft design, but using `<` at the call site means the parser would require infinite lookahead (see the draft design for details). There is also an ambiguity objection raised in the draft for using square brackets, but Alan Fox offered a solution, which I used in my example. I don't personally have anything against angle brackets in principle though. -- 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.
Re: [go-nuts] Failed iterator proposals?
Axel Wagner : > But personally I don't see the point of introducing a custom iterator concept > just to *occasionally* save one or two lines of code. Don't despise saving lines of code. There's a well-known law the name of which I've forgotten that defect rates per KLOC are rougly constant across languages. Accordingly, what you're really doing when you enable your language to do more in fewer LOC is lowering your defect load. Thart's not really how I think of it, though. I think in terms of reducing eyeball friction. Always a virtue when you're programming at scale. These might be the same issue, actually. -- http://www.catb.org/~esr/";>Eric S. Raymond 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.
Re: [go-nuts] Failed iterator proposals?
Tamás Gulácsi : > You can achive sth like this with a function returning a chan. I'm aware of this. There's a good essay on iterator patterns https://ewencp.org/blog/golang-iterators/index.html that goes into three of the possibilties in detail. It covers the problem with the channel idiom, too - slowness due to channel scheduler overhead. Can be pretty bad - I've verified this by benchmarking. -- http://www.catb.org/~esr/";>Eric S. Raymond 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.
[go-nuts] Failed iterator proposals?
You can achive sth like this with a function returning a chan. Or create a filtering function and apply it, creating a second slice. Neither is perfect - the first is closer to the python generator, the secobd is to the declared use case. -- 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.
Re: [go-nuts] Failed iterator proposals?
I am sure it has been discussed, but why the aversion to using < > in type declarations? I guess I just don’t understand using bracketing notations that are already used for something else. When I see [] I can immediately see - ah, slice/map reference. When I see () I can immediately see - ah function (or expression grouping which is similar) Since generics will be optional (I assume), I think it should have a notation that is not used frequently, so the generic aspects stand out. > On Oct 22, 2018, at 2:41 PM, Ian Denhardt wrote: > > Observation: this discussion is very close to the debate around operator > overloading. In fact, if we add generics to the language, we could > define interfaces (I will use Alan Fox's square bracket syntax, as I > think it improves readability): > > type Iterator[type Elem] interface { >Next() bool >Current() Elem > } > > type Iterable[type Elem] interface { >Iter() Iterator[Elem] > } > > Then, generic iterator code could look like: > >for it := collection.Iter(); it.Next(); { >cur := it.Current() >// ... >} > > In this case, allowing range to be used with user-defined collections is > more-or-less a special case of operator overloading. > > I'm not making a value judgement here, just an observation. The > arguments for and against I think are almost 1-to-1. > > Quoting 'Axel Wagner' via golang-nuts (2018-10-22 15:20:37) >> 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 <[1]e...@thyrsus.com> >> wrote: >> >> David Anderson <[2]d...@natulte.net>: >>> [3]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. >> -- >> � � � � � � � � http://www.catb.org/~esr/";>Eric >> S. Raymond >>
Re: [go-nuts] Failed iterator proposals?
Observation: this discussion is very close to the debate around operator overloading. In fact, if we add generics to the language, we could define interfaces (I will use Alan Fox's square bracket syntax, as I think it improves readability): type Iterator[type Elem] interface { Next() bool Current() Elem } type Iterable[type Elem] interface { Iter() Iterator[Elem] } Then, generic iterator code could look like: for it := collection.Iter(); it.Next(); { cur := it.Current() // ... } In this case, allowing range to be used with user-defined collections is more-or-less a special case of operator overloading. I'm not making a value judgement here, just an observation. The arguments for and against I think are almost 1-to-1. Quoting 'Axel Wagner' via golang-nuts (2018-10-22 15:20:37) >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 <[1]e...@thyrsus.com> >wrote: > > David Anderson <[2]d...@natulte.net>: > > [3]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. > -- > � � � � � � � � http://www.catb.org/~esr/";>Eric > S. Raymond > My work is funded by the Internet Civil Engineering Institute: > [5]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 [6]golang-nuts+unsubscr...@googlegroups.com. > For more options, visit [7]https://groups.google.com/d/optout. > >-- >You received t
Re: [go-nuts] Failed iterator proposals?
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 wrote: > David Anderson : > > 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. > -- > http://www.catb.org/~esr/";>Eric S. Raymond > > 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.
Re: [go-nuts] Failed iterator proposals?
David Anderson : > 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. -- http://www.catb.org/~esr/";>Eric S. Raymond 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.
Re: [go-nuts] Failed iterator proposals?
Thank you, that was a helpful response. -- 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.
Re: [go-nuts] Failed iterator proposals?
The pattern you describe is used in several stdlib packages (notably bufio.Scanner, which leads to a loop that looks like `for scanner.Scan() { doStuff(scanner.Text()) }`. The only variation from your example is that in the stdlib, `iterator.Continue()` both tests for the end condition and advances the iterator state. With that change, it ends up not much more verbose than the second syntax you suggest. 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. 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. I think that's the big non-technical question to address, aside from the mechanics of syntax and semantics. - Dave On Sun, Oct 21, 2018 at 5:41 PM Eric Raymond wrote: > I have a real-world case where I need Python style iterators for > performance. It's not good to eager-evaluate an event-list 259K items when > you know that in the typical case you're only going to select two or three > orders of magnitude fewer of them to be passed to a work function. (The > list is of commit events in a version-control repository; the selector > might be something like "commited within 24 hours of time t"). > > There's an obvious, clumsy way to do this by having a factory pass back a > stateful iterator object: > > for iterator := IteratorFactory(selector); iterator.Continue();iterator. > Next(){ >DoSomethingWith(iterator.Value()) > } > > > What one would really like to be able to do, though, is much more concise: > > for i, v := range iteratorFunction() { > DoSomethingWith(i, v) > } > > Before I post an RFE, are there rejected iterator proposals I should read > so I don't waste anyone's time on stale ideas? > > > -- > 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.
[go-nuts] Failed iterator proposals?
I have a real-world case where I need Python style iterators for performance. It's not good to eager-evaluate an event-list 259K items when you know that in the typical case you're only going to select two or three orders of magnitude fewer of them to be passed to a work function. (The list is of commit events in a version-control repository; the selector might be something like "commited within 24 hours of time t"). There's an obvious, clumsy way to do this by having a factory pass back a stateful iterator object: for iterator := IteratorFactory(selector); iterator.Continue();iterator.Next (){ DoSomethingWith(iterator.Value()) } What one would really like to be able to do, though, is much more concise: for i, v := range iteratorFunction() { DoSomethingWith(i, v) } Before I post an RFE, are there rejected iterator proposals I should read so I don't waste anyone's time on stale ideas? -- 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.