RFC on range design for D2

Sergey Gromov snake.scaly at gmail.com
Thu Sep 11 02:18:01 PDT 2008


Steven Schveighoffer <schveiguy at yahoo.com> wrote:
> What I see as the biggest downside is the cumbersome and verbose code of 
> moving the 'iterator' around, as every time I want to move forward, I 
> construct a new range, and every time I want to move backwards I construct a 
> new range (and construct a new 'center' afterwards).  So a 'move back one' 
> looks like:
> 
> auto before = all.before(center);
> if(!before.isEmpty)
>   center = before.pop.end;
> 
> And to move forward it's:
> auto after = all.after(center);
> if(!after.isEmpty)
>   center = after.next.begin;
> 
> To get the value there, I have to do:
> all.after(center).left // or whatever gets decided as the 'get first value 
> of range' member
> 
> or if opStar is used:
> 
> *all.after(center);
> 
> I much prefer:
> 
> forward:
> if(center != list.end)
>     ++center;
> 
> reverse:
> if(center != list.begin)
>    --center;
> 
> get value:
> *center;
> 
> Especially without all the extra overhead
> 
> I see both methods as being just as open to mistakes, the first more-so, and 
> more difficult to comprehend (at least for me).

Yes, these are valid points, I completely agree.  But there are also 
other points.  Let me voice some of them.

1.  Probably most important.  You say here that ranges suck at 
incremental bidirectional iteration over a linked list, as Bill aslo 
agrees with.  This seems true.  But this sort of iteration is not a goal 
in its own.  It's just an idiomatic *iterator* solution for a range of 
real-world problems.  I can't think of any such problem from the top of 
my head but it's probably a matter of my education.  Bill proposed one 
already.

I want to say that I believe that for any such real-world problem there 
is a range solution that's probably better than a direct mapping of an 
existing iterator solution.  The analogy would be trying to write in C++ 
as if you were using Python, or Haskell, and then declare that C++ sucks 
because it requires bulky, inefficient and error-prone code to implement 
simple functional idioms.  Different languages require different idioms 
and ranges are a different language from iterators.

For instance, Bill's undo/redo stack consisted of two entities: a list 
of operations, and a cursor. It was OK and natural with iterators.  It 
sucks with ranges.  Okay, I'm also going to use two entities: undo stack 
and redo stacks. Undo => pop from one, push to another.  New operation 
=> push undo, trash redo.  Doesn't it look simpler and safer?  Well, it 
doesn't use ranges, at least from the user perspective, so what?

I also believe that a regular expression engine would benefit from using 
ranges rather than suffer.

2.  There was a special case that a center marker couldn't have been 
dereferenced.  Let's imagine you really needed it.  OK, no problem.  
Let's create a special kind of ranges, Cursor.  Cursor always contains 
one element.  Its begin points to that element and its end is calculated 
so that it always points after that element no matter what.  This is as 
valid as having an iterator pointing to that same element because you 
must guarantee in both cases that an iterator is dereferenceable.  This 
is ad-hoc, yes, but an EOF iterator in C++ is no less ad-hoc.


More information about the Digitalmars-d-announce mailing list