std.container & ranges

Christophe travert at phare.normalesup.org
Thu Nov 3 09:32:06 PDT 2011


"Steven Schveighoffer" , dans le message (digitalmars.D.learn:30402), a
> The primitive for a container is remove(range).  Ranges are essential to  
> containers, and should be the major interface to them.

Programmers have to learn ranges to use containers. Hiding ranges is not 
helping them.

But here, it is more complicated than that, because range may be more 
powerful than iterators, they are less friendly to use when a single 
element reference has to be used.

c.remove(find(c.all, E));

will not remove the first occurence of E, but all elements beyond E.
so instead we have to write:

c.remove(take(find(c[], E), 1));

Then it's too much.

The problem is that range are not practical to refer to a single element 
in the container. We need to have single-element reference to manipulate 
the range. Then a function should be used to find such one-element 
reference. std.find is already taken, and can hardly be changed 
(although it should be name popUntil), but we can still use a find 
method of the container.

auto r = take(find(c[], E), 1);

should just be written:

auto r = c.find(E);

Then the syntax to remove a single element from c is acceptable:
c.remove(c.find(E)).

Now let us remove several consecutive elements from c, let us say, all 
elements between the value E and the next value F:

| auto r = find(c[], E);
| int i=0;
| foreach(e, r)
|   if (e == F) break;
|   else ++i;
| c.remove(take(r, i+1));

That is not practical at all, and in addition, it is not efficient, 
since r is walked again from E to F.

If we add little methods to single element reference to make them behave 
a little like iterators, we can recreate ranges from two single element 
references, and regain all the power of iterators. To remove all 
elements from E to the next F included:

auto r = c.find( E);
c.remove(r, r.find(F)++);
// or c.remove(range(r, r.find(F)++));

(I use the find method a bit like a joker in this exemple, it is just 
to get the idea).

In conclusion, to refer to a single element of a container for simple 
operations, range looses against iterator. Ranges even loose to refer to 
a range of consecutive elements...
Many alternatives are possible, but a simple iterator structure to refer 
to a single element, and that you can combine to recreate a range (and 
use all range algorithms) would be enough, and would complete the range 
interface to make them have no drawback against iterators.


More information about the Digitalmars-d-learn mailing list