Re: [go-nuts] Failed iterator proposals?

2018-10-25 Thread Nigel Tao
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?

2018-10-25 Thread Burak Serdar
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?

2018-10-25 Thread robert engels
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?

2018-10-25 Thread Eric S. Raymond
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?

2018-10-25 Thread 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.

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?

2018-10-25 Thread Eric S. Raymond
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?

2018-10-25 Thread Eric S. Raymond
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?

2018-10-24 Thread 'Axel Wagner' via golang-nuts
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?

2018-10-24 Thread Jan Mercl
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?

2018-10-24 Thread Eric S. Raymond
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?

2018-10-22 Thread 'Axel Wagner' via golang-nuts
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?

2018-10-22 Thread Ian Denhardt
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?

2018-10-22 Thread Eric S. Raymond
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?

2018-10-22 Thread Eric S. Raymond
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?

2018-10-22 Thread Tamás Gulácsi
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?

2018-10-22 Thread robert engels
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?

2018-10-22 Thread Ian Denhardt
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?

2018-10-22 Thread 'Axel Wagner' via golang-nuts
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?

2018-10-22 Thread Eric S. Raymond
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?

2018-10-22 Thread Eric Raymond
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?

2018-10-21 Thread David Anderson
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?

2018-10-21 Thread Eric Raymond
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.