www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Ranges and/versus iterators

reply clueless bystander <clueless bystander.com> writes:
Watching D evolve from the outside there seems to be a lot of ongoing discussion
on this newsgroup about the D range idiom which is somehow opposed to
conventional
thinking about iterators.

Can someone please explain in plain words just exactly what a range is and how
it differs from the iterator concept (if that's appropriate???) and what are
the benefits
from a data modeling and access perspective.

Sure, I'm clueless, though suspect many other bystanders would appreciate a
succinct heads-up.

Thanks,
clueless bystander
Mar 23 2010
next sibling parent reply "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
clueless bystander wrote:
 Watching D evolve from the outside there seems to be a lot of ongoing
discussion
 on this newsgroup about the D range idiom which is somehow opposed to
conventional
 thinking about iterators.
 
 Can someone please explain in plain words just exactly what a range is and how
 it differs from the iterator concept (if that's appropriate???) and what are
the benefits
 from a data modeling and access perspective.
 
 Sure, I'm clueless, though suspect many other bystanders would appreciate a
 succinct heads-up.
 
 Thanks,
 clueless bystander

I'm probably not the right person to answer your question, since I have virtually no experience with C++ iterators. Instead I'll just refer you to Andrei's own article on the subject: http://www.informit.com/articles/article.aspx?p=1407357 Please don't hesitate to ask again if it didn't clear things up for you. :) -Lars
Mar 23 2010
next sibling parent clueless bystander <clueless bystander.com> writes:
Lars T. Kyllingstad Wrote:

 clueless bystander wrote:
 Watching D evolve from the outside there seems to be a lot of ongoing
discussion
 on this newsgroup about the D range idiom which is somehow opposed to
conventional
 thinking about iterators.
 
 Can someone please explain in plain words just exactly what a range is and how
 it differs from the iterator concept (if that's appropriate???) and what are
the benefits
 from a data modeling and access perspective.
 
 Sure, I'm clueless, though suspect many other bystanders would appreciate a
 succinct heads-up.
 
 Thanks,
 clueless bystander

I'm probably not the right person to answer your question, since I have virtually no experience with C++ iterators. Instead I'll just refer you to Andrei's own article on the subject: http://www.informit.com/articles/article.aspx?p=1407357 Please don't hesitate to ask again if it didn't clear things up for you. :) -Lars

Thanks Lars. I'm not quite willing to accept that 15 pages is succinct but if that's what it takes to build up the background then that's what it takes. I'm up to page 3 now and, btw, like the way the author *does not* mince his words: "Such matters as a polynomial slowdown were too mundane to hinder the power of S-lists, so some functional programmers got imbued with an attitude of contempt toward arrays and associative arrays, data structures essential to many algorithms." c.b.
Mar 23 2010
prev sibling parent reply clueless bystander <clueless bystander.com> writes:
Lars T. Kyllingstad Wrote:

 clueless bystander wrote:
 Watching D evolve from the outside there seems to be a lot of ongoing
discussion
 on this newsgroup about the D range idiom which is somehow opposed to
conventional
 thinking about iterators.
 
 Can someone please explain in plain words just exactly what a range is and how
 it differs from the iterator concept (if that's appropriate???) and what are
the benefits
 from a data modeling and access perspective.
 
 Sure, I'm clueless, though suspect many other bystanders would appreciate a
 succinct heads-up.
 
 Thanks,
 clueless bystander

I'm probably not the right person to answer your question, since I have virtually no experience with C++ iterators. Instead I'll just refer you to Andrei's own article on the subject: http://www.informit.com/articles/article.aspx?p=1407357 Please don't hesitate to ask again if it didn't clear things up for you. :) -Lars

Yes, well, thanks again. The first 7 pages seemed to have plausible arguments but the going get tough thereafter. Maybe the reason ranges are not popular is that they are hard to explain even though they might be simple and obvious in hindsight. Sigh, c.b.
Mar 23 2010
next sibling parent "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
clueless bystander wrote:
 Lars T. Kyllingstad Wrote:
 
 clueless bystander wrote:
 Watching D evolve from the outside there seems to be a lot of ongoing
discussion
 on this newsgroup about the D range idiom which is somehow opposed to
conventional
 thinking about iterators.

 Can someone please explain in plain words just exactly what a range is and how
 it differs from the iterator concept (if that's appropriate???) and what are
the benefits
 from a data modeling and access perspective.

 Sure, I'm clueless, though suspect many other bystanders would appreciate a
 succinct heads-up.

 Thanks,
 clueless bystander

I'm probably not the right person to answer your question, since I have virtually no experience with C++ iterators. Instead I'll just refer you to Andrei's own article on the subject: http://www.informit.com/articles/article.aspx?p=1407357 Please don't hesitate to ask again if it didn't clear things up for you. :) -Lars

Yes, well, thanks again. The first 7 pages seemed to have plausible arguments but the going get tough thereafter. Maybe the reason ranges are not popular is that they are hard to explain even though they might be simple and obvious in hindsight. Sigh, c.b.

The reason ranges are not popular is because they haven't had time to become popular yet. The range concept itself is rather new, not much older than the article I referred you to, and AFAIK it's only been implemented in the D2 standard library. I'm sure there are several people on this forum that can give you a satisfactory (and succinct) answer. You may want to check back in a few hours, when activity picks up. FWIW, I don't think the concept of ranges is very hard to grasp. I just haven't used them that much, that's why I don't want to be the one to answer your question (and, like I said before, I have never used C++ iterators so I can't compare them either). -Lars
Mar 23 2010
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 03/23/2010 06:58 AM, clueless bystander wrote:
 Lars T. Kyllingstad Wrote:

 clueless bystander wrote:
 Watching D evolve from the outside there seems to be a lot of ongoing
discussion
 on this newsgroup about the D range idiom which is somehow opposed to
conventional
 thinking about iterators.

 Can someone please explain in plain words just exactly what a range is and how
 it differs from the iterator concept (if that's appropriate???) and what are
the benefits
 from a data modeling and access perspective.

 Sure, I'm clueless, though suspect many other bystanders would appreciate a
 succinct heads-up.

 Thanks,
 clueless bystander

I'm probably not the right person to answer your question, since I have virtually no experience with C++ iterators. Instead I'll just refer you to Andrei's own article on the subject: http://www.informit.com/articles/article.aspx?p=1407357 Please don't hesitate to ask again if it didn't clear things up for you. :) -Lars

Yes, well, thanks again. The first 7 pages seemed to have plausible arguments but the going get tough thereafter. Maybe the reason ranges are not popular is that they are hard to explain even though they might be simple and obvious in hindsight. Sigh, c.b.

Thank you for your interest. The article (http://erdani.com/publications/on-iteration.html) is long because following my keynote talk at BoostCon 2009, I've received a flurry of emails asking me to flesh out the ranges design in greater detail and to better motivate them. That article not only describes the design, but it also explains the historical artifacts that led to today's imperfect state of affairs, motivates defining ranges with categories, and gives examples. The price for such thoroughness is - sorry - size. If you are familiar with STL iterators and GoF-style iterators (with hasmore/get/advance), ranges are so simple, they define themselves: a range is a GoF-style iterator that recognizes the necessity of STL's iterator categories (input, forward, bidirectional, and random). All the rest is aftermath. Andrei
Mar 23 2010
prev sibling next sibling parent Jesse Phillips <jessekphillips+D gmail.com> writes:
I think a good way to learn ranges is by looking at the interface to them,
compared to those used by other languages. For one thing, C++ iterators are way
more complicated than what you will find in many other languages; for example
Java's iterator interface[1] is similar to a D range[2].

In both languages the interface is 3 functions (there are many types of ranges
which require more, but only one kind of iterator).

Java:
bool hasNext()
E next()
void remove()

D:
bool empty()
E front()
void popFront()

These look almost identical but the semantics are very different. For example,
hasNext() requires a look-ahead, while empty() does not. This is important
since you may not be able to look ahead in a range.

next() performs the equivalent of calling front(); popFront(); And remove() has
nothing to do with the iterator as it performs on the underlining collection.

Removing the look-ahead is probably one of the biggest improvements over Java's
iterator.

1. http://java.sun.com/j2se/1.5.0/docs/api/java/util/Iterator.html
2. http://digitalmars.com/d/2.0/phobos/std_range.html#isInputRange

clueless bystander Wrote:

 Watching D evolve from the outside there seems to be a lot of ongoing
discussion
 on this newsgroup about the D range idiom which is somehow opposed to
conventional
 thinking about iterators.
 
 Can someone please explain in plain words just exactly what a range is and how
 it differs from the iterator concept (if that's appropriate???) and what are
the benefits
 from a data modeling and access perspective.
 
 Sure, I'm clueless, though suspect many other bystanders would appreciate a
 succinct heads-up.
 
 Thanks,
 clueless bystander

Mar 23 2010
prev sibling next sibling parent Igor Lesik <curoles yahoo.com> writes:
Can someone please explain in plain words just exactly what a range is and=

what are the benefits=0A>from a data modeling and access perspective.=0A= =0ACheck Andrei's presentation "Iterators must go":=0Ahttp://www.slideshare= .net/rawwell/iteratorsmustgo=0A=0AI=A0am interested myself to know how rang= es=0Aare envisioned to be in D. Does the book talk=0Aabout ranges?=0A=0A=0A= =0A
Mar 23 2010
prev sibling next sibling parent reply Fawzi Mohamed <fawzi gmx.ch> writes:
Andrei, as the topic just came up a comment on the range interface.
Just for plain forward iterators iterators having

bool empty()
E front()
void popFront()

makes the interface non reentrant.
For that purpose having a single function is better.
I use

	bool popFront(ref T t)
	// returns true if there is a next element, and in that case returns  
it in t

this can be used by several consumers concurrently without problems  
and creating filters, combiners,... is simple.
Another advantage is that a single object can implement several  
iterators.
A disadvantage is that even if there is a single iterator D makes type  
inference cumbersome, i.e. you cannot simply use auto, as in a loop  
you have to declare the variable before using it as the loop is
T a;
while (it.popFront(a)){
//...
}
Mar 23 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 03/23/2010 02:45 PM, Fawzi Mohamed wrote:
 Andrei, as the topic just came up a comment on the range interface.
 Just for plain forward iterators iterators having

 bool empty()
 E front()
 void popFront()

 makes the interface non reentrant.
 For that purpose having a single function is better.
 I use

 bool popFront(ref T t)
 // returns true if there is a next element, and in that case returns it
 in t

 this can be used by several consumers concurrently without problems and
 creating filters, combiners,... is simple.
 Another advantage is that a single object can implement several iterators.
 A disadvantage is that even if there is a single iterator D makes type
 inference cumbersome, i.e. you cannot simply use auto, as in a loop you
 have to declare the variable before using it as the loop is
 T a;
 while (it.popFront(a)){
 //...
 }

We've discussed this extensively, and I lost sleep over this simple matter more than once. The main problem with bool popFront(ref E) is that it doesn't work meaningfully for containers that expose references to their elements. The interface with front() leaves it to the range to return E or ref E. An alternative is this: bool empty(); ref E getNext(); // ref or no ref I'm thinking seriously of defining input ranges that way. The underlying notion is that you always move forward - getting an element is simultaneous with moving to the next. Andrei
Mar 23 2010
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 03/23/2010 03:46 PM, Steven Schveighoffer wrote:
 On Tue, 23 Mar 2010 16:34:24 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:

 On 03/23/2010 02:45 PM, Fawzi Mohamed wrote:
 Andrei, as the topic just came up a comment on the range interface.
 Just for plain forward iterators iterators having

 bool empty()
 E front()
 void popFront()

 makes the interface non reentrant.
 For that purpose having a single function is better.
 I use

 bool popFront(ref T t)
 // returns true if there is a next element, and in that case returns it
 in t

 this can be used by several consumers concurrently without problems and
 creating filters, combiners,... is simple.
 Another advantage is that a single object can implement several
 iterators.
 A disadvantage is that even if there is a single iterator D makes type
 inference cumbersome, i.e. you cannot simply use auto, as in a loop you
 have to declare the variable before using it as the loop is
 T a;
 while (it.popFront(a)){
 //...
 }

We've discussed this extensively, and I lost sleep over this simple matter more than once. The main problem with bool popFront(ref E) is that it doesn't work meaningfully for containers that expose references to their elements. The interface with front() leaves it to the range to return E or ref E. An alternative is this: bool empty(); ref E getNext(); // ref or no ref I'm thinking seriously of defining input ranges that way. The underlying notion is that you always move forward - getting an element is simultaneous with moving to the next.

A while back, you identified one of the best interfaces for input ranges: E* getNext(); Which allows for null returns when no data is left. The drawback is that E must be either referenced or allocated on the heap (providing storage to the function is an option). But the killer issue was that safeD would not allow it. However, in recent times, you have hinted that safeD may allow pointers, but disallow bad pointer operations. In light of this, can we reconsider this interface, or other alternatives using pointers? I've always felt that if we were to define ranges for streams in a non-awkward way, we would need an "all in one" operation, since not only does getting data from the range move the range, but checking for empty might also move the range (empty on a stream means you tried to read and got nothing).

I'd gladly reconsider E* getNext(), and I like it a lot, but that doesn't accommodate ranges that want to return rvalues without storing them (e.g. a range using getchar() as a back-end, and generally streams that don't correspond to stuff stored in memory). If it's not in memory, there's no pointer to it. Andrei
Mar 23 2010
prev sibling next sibling parent reply grauzone <none example.net> writes:
Steven Schveighoffer wrote:
 A while back, you identified one of the best interfaces for input ranges:
 
 E* getNext();
 
 Which allows for null returns when no data is left.  The drawback is 
 that E must be either referenced or allocated on the heap (providing 
 storage to the function is an option).  But the killer issue was that 
 safeD would not allow it.  However, in recent times, you have hinted 

Nullable!(E) getNext(); ?
Mar 23 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 03/23/2010 04:06 PM, grauzone wrote:
 Steven Schveighoffer wrote:
 A while back, you identified one of the best interfaces for input ranges:

 E* getNext();

 Which allows for null returns when no data is left. The drawback is
 that E must be either referenced or allocated on the heap (providing
 storage to the function is an option). But the killer issue was that
 safeD would not allow it. However, in recent times, you have hinted

Nullable!(E) getNext(); ?

And if returning a reference...? Andrei
Mar 23 2010
parent grauzone <none example.net> writes:
Andrei Alexandrescu wrote:
 On 03/23/2010 04:06 PM, grauzone wrote:
 Steven Schveighoffer wrote:
 A while back, you identified one of the best interfaces for input 
 ranges:

 E* getNext();

 Which allows for null returns when no data is left. The drawback is
 that E must be either referenced or allocated on the heap (providing
 storage to the function is an option). But the killer issue was that
 safeD would not allow it. However, in recent times, you have hinted

Nullable!(E) getNext(); ?

And if returning a reference...?

Extend auto ref to template parameters: struct Nullable(auto ref T) { ... } T would be actually a reference type if and only if you could return a reference to the variable the template parameter was inferred from from a SafeD function. Basically, the compiler would know that references to T can be passed around freely. (SafeD allows ref returns under circumstances.) Not a solution I would prefer, but in the spirit of the design of D2 and SafeD in general.
 Andrei

Mar 23 2010
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 03/23/2010 05:41 PM, Fawzi Mohamed wrote:
 On 23-mar-10, at 21:34, Andrei Alexandrescu wrote:

 [...]
 We've discussed this extensively, and I lost sleep over this simple
 matter more than once. The main problem with bool popFront(ref E) is
 that it doesn't work meaningfully for containers that expose
 references to their elements.

yes I agree that it is a difficult problem, the single function works well in the basic iterator case, but does not generalize well to modifiable values. In most cases I resorted to returning pointers. The templates that generate opApply (still D1.0 ;) from that is smart enough to remove the pointer when possible as the ref already gives that. Still not perfect, as always there are tradeoffs...
 The interface with front() leaves it to the range to return E or ref E.

 An alternative is this:

 bool empty();
 ref E getNext(); // ref or no ref

 I'm thinking seriously of defining input ranges that way. The
 underlying notion is that you always move forward - getting an element
 is simultaneous with moving to the next.

already better (for basic iterators), but still not reentrant, if another thread executes between empty and getNext...

It can't :o).
 anyway any choice has some drawbacks... I like bool next(ref T) because
 it works well also for streams... and somehow (using T* or not depending
 on the type) can accommodate all iteration needs.
 Not perfectly nice, but workable.

next(ref T) works well _only_ on streams. It works badly on containers. Andrei
Mar 23 2010
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 23 Mar 2010 16:34:24 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 On 03/23/2010 02:45 PM, Fawzi Mohamed wrote:
 Andrei, as the topic just came up a comment on the range interface.
 Just for plain forward iterators iterators having

 bool empty()
 E front()
 void popFront()

 makes the interface non reentrant.
 For that purpose having a single function is better.
 I use

 bool popFront(ref T t)
 // returns true if there is a next element, and in that case returns it
 in t

 this can be used by several consumers concurrently without problems and
 creating filters, combiners,... is simple.
 Another advantage is that a single object can implement several  
 iterators.
 A disadvantage is that even if there is a single iterator D makes type
 inference cumbersome, i.e. you cannot simply use auto, as in a loop you
 have to declare the variable before using it as the loop is
 T a;
 while (it.popFront(a)){
 //...
 }

We've discussed this extensively, and I lost sleep over this simple matter more than once. The main problem with bool popFront(ref E) is that it doesn't work meaningfully for containers that expose references to their elements. The interface with front() leaves it to the range to return E or ref E. An alternative is this: bool empty(); ref E getNext(); // ref or no ref I'm thinking seriously of defining input ranges that way. The underlying notion is that you always move forward - getting an element is simultaneous with moving to the next.

A while back, you identified one of the best interfaces for input ranges: E* getNext(); Which allows for null returns when no data is left. The drawback is that E must be either referenced or allocated on the heap (providing storage to the function is an option). But the killer issue was that safeD would not allow it. However, in recent times, you have hinted that safeD may allow pointers, but disallow bad pointer operations. In light of this, can we reconsider this interface, or other alternatives using pointers? I've always felt that if we were to define ranges for streams in a non-awkward way, we would need an "all in one" operation, since not only does getting data from the range move the range, but checking for empty might also move the range (empty on a stream means you tried to read and got nothing). -Steve
Mar 23 2010
prev sibling next sibling parent Fawzi Mohamed <fawzi gmx.ch> writes:
On 23-mar-10, at 21:34, Andrei Alexandrescu wrote:

 [...]
 We've discussed this extensively, and I lost sleep over this simple  
 matter more than once. The main problem with bool popFront(ref E) is  
 that it doesn't work meaningfully for containers that expose  
 references to their elements.

yes I agree that it is a difficult problem, the single function works well in the basic iterator case, but does not generalize well to modifiable values. In most cases I resorted to returning pointers. The templates that generate opApply (still D1.0 ;) from that is smart enough to remove the pointer when possible as the ref already gives that. Still not perfect, as always there are tradeoffs...
 The interface with front() leaves it to the range to return E or ref  
 E.

 An alternative is this:

 bool empty();
 ref E getNext(); // ref or no ref

 I'm thinking seriously of defining input ranges that way. The  
 underlying notion is that you always move forward - getting an  
 element is simultaneous with moving to the next.

already better (for basic iterators), but still not reentrant, if another thread executes between empty and getNext... anyway any choice has some drawbacks... I like bool next(ref T) because it works well also for streams... and somehow (using T* or not depending on the type) can accommodate all iteration needs. Not perfectly nice, but workable. Fawzi
Mar 23 2010
prev sibling next sibling parent Fawzi Mohamed <fawzi gmx.ch> writes:
--Apple-Mail-10--979993206
Content-Type: text/plain;
	charset=US-ASCII;
	format=flowed;
	delsp=yes
Content-Transfer-Encoding: 7bit


On 23-mar-10, at 21:51, Andrei Alexandrescu wrote:

 On 03/23/2010 03:46 PM, Steven Schveighoffer wrote:
 On Tue, 23 Mar 2010 16:34:24 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:

 [...]
 A while back, you identified one of the best interfaces for input  
 ranges:

 E* getNext();

 Which allows for null returns when no data is left. The drawback is  
 that
 E must be either referenced or allocated on the heap (providing  
 storage
 to the function is an option). But the killer issue was that safeD  
 would
 not allow it. However, in recent times, you have hinted that safeD  
 may
 allow pointers, but disallow bad pointer operations. In light of  
 this,
 can we reconsider this interface, or other alternatives using  
 pointers?

 I've always felt that if we were to define ranges for streams in a
 non-awkward way, we would need an "all in one" operation, since not  
 only
 does getting data from the range move the range, but checking for  
 empty
 might also move the range (empty on a stream means you tried to  
 read and
 got nothing).


yes that also makes filters/combiners really nice to write. the basic thing is that you have to return two things, 1. if there is more and 2. if yes the element.
 I'd gladly reconsider E* getNext(), and I like it a lot, but that  
 doesn't accommodate ranges that want to return rvalues without  
 storing them (e.g. a range using getchar() as a back-end, and  
 generally streams that don't correspond to stuff stored in memory).  
 If it's not in memory, there's no pointer to it.

E* getNext would probably also be workable, at the cost of storing one element. But then as andrei correctly points out one still cannot expect the pointer to be valid after one iteration, so as soon as you don't have memory storage you loose thread safety... Now reentrancy/thread safety is not necessarily the most important thing for iterators, but I like that my queues, sources of work can have the same interface. --Apple-Mail-10--979993206 Content-Type: text/html; charset=US-ASCII Content-Transfer-Encoding: quoted-printable <html><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: space; = -webkit-line-break: after-white-space; "><br><div><div>On 23-mar-10, at = 21:51, Andrei Alexandrescu wrote:</div><br = class=3D"Apple-interchange-newline"><blockquote type=3D"cite"><div>On = 03/23/2010 03:46 PM, Steven Schveighoffer wrote:<br><blockquote = type=3D"cite">On Tue, 23 Mar 2010 16:34:24 -0400, Andrei = Alexandrescu<br></blockquote><blockquote type=3D"cite">&lt;<a = href=3D"mailto:SeeWebsiteForEmail erdani.org">SeeWebsiteForEmail erdani.or= g</a>&gt; wrote:<br></blockquote><blockquote = type=3D"cite"><br></blockquote><blockquote type=3D"cite"><font = class=3D"Apple-style-span" = color=3D"#540000">[...]</font></blockquote><blockquote type=3D"cite">A = while back, you identified one of the best interfaces for input = ranges:<br></blockquote><blockquote = type=3D"cite"><br></blockquote><blockquote type=3D"cite">E* = getNext();<br></blockquote><blockquote = type=3D"cite"><br></blockquote><blockquote type=3D"cite">Which allows = for null returns when no data is left. The drawback is = that<br></blockquote><blockquote type=3D"cite">E must be either = referenced or allocated on the heap (providing = storage<br></blockquote><blockquote type=3D"cite">to the function is an = option). But the killer issue was that safeD = would<br></blockquote><blockquote type=3D"cite">not allow it. However, = in recent times, you have hinted that safeD = may<br></blockquote><blockquote type=3D"cite">allow pointers, but = disallow bad pointer operations. In light of = this,<br></blockquote><blockquote type=3D"cite">can we reconsider this = interface, or other alternatives using = pointers?<br></blockquote><blockquote = type=3D"cite"><br></blockquote><blockquote type=3D"cite">I've always = felt that if we were to define ranges for streams in = a<br></blockquote><blockquote type=3D"cite">non-awkward way, we would = need an "all in one" operation, since not = only<br></blockquote><blockquote type=3D"cite">does getting data from = the range move the range, but checking for = empty<br></blockquote><blockquote type=3D"cite">might also move the = range (empty on a stream means you tried to read = and<br></blockquote><blockquote type=3D"cite">got = nothing).<br></blockquote></div></blockquote><div><br></div>yes that = also makes filters/combiners really nice to write.</div><div>the basic = thing is that you have to return two things, 1. if there is more and 2. = if yes the element.</div><div><br><blockquote type=3D"cite"><div>I'd = gladly reconsider E* getNext(), and I like it a lot, but that doesn't = accommodate ranges that want to return rvalues without storing them = (e.g. a range using getchar() as a back-end, and generally streams that = don't correspond to stuff stored in memory). If it's not in memory, = there's no pointer to it.<br></div></blockquote><div><br></div><div>E* = getNext would probably also be workable, at the cost of storing one = element. But then as andrei correctly points out one still cannot expect = the pointer to be valid after one iteration, so as soon as you don't = have memory storage you loose thread = safety...</div><div><br></div><div>Now reentrancy/thread safety is not = necessarily the most important thing for iterators, but I like that my = queues, sources of work can have the same = interface.</div></div><br></body></html>= --Apple-Mail-10--979993206--
Mar 23 2010
prev sibling parent Neal Becker <ndbecker2 gmail.com> writes:
clueless bystander wrote:

 Watching D evolve from the outside there seems to be a lot of ongoing
 discussion on this newsgroup about the D range idiom which is somehow
 opposed to conventional thinking about iterators.
 
 Can someone please explain in plain words just exactly what a range is and
 how it differs from the iterator concept (if that's appropriate???) and
 what are the benefits from a data modeling and access perspective.
 
 Sure, I'm clueless, though suspect many other bystanders would appreciate
 a succinct heads-up.
 
 Thanks,
 clueless bystander

Wow, what a great email address!
Mar 27 2010