On Monday 21 February 2011 21:04:47 %u wrote:
> > remove takes a range type which is the range type for the
> 
> container that it's on. That makes sense. It's obviously not going
> to be able to a take an arbitrary range and remove that from itself.
> How would it know which elements in that range corresponded to which
> elements in itself - especially when it could be a range which skips
> elements or something similar? So, _that_ part makes sense.
> 
> I'm wondering, what was the reason for making a "remove range X from
> Y" method in the first place? To me, that's not a "remove"
> operation; if anything, it's the "removeAll" operation, but I'd
> actually call it "subtract" (because it's the set subtraction
> operation... although there can be duplicates).
> 
> If we change remove to only take in a single element, wouldn't its
> implementation then be trivial? (For a range, just return a filter
> that removes the element. For a container, actually remove the
> element. For ranges that also behave like containers -- like arrays
> -- I have no idea.)
> 
> Does this sound like a good idea?

Removing a range is not necessarily related to removing an element with a 
particular value. Sure, a method could be added to the various container types 
which takes a value and removes the first instance of that value from the 
container, but that's not what remove is necessarily trying to do. It's like 
erase in C++'s standard library which takes two iterators. There are plenty of 
situations where removing a range makes sense. The odd bit with remove in 
Phobos 
vs erase in the STL is that with iterators, you can give a single iterator to 
indicate a single element whereas you can't do that with a range. So, remove 
takes a range, and if you want to remove a single element, that range only has 
one element in it. It's a bit weird, but that's fine.

The typical way to remove an element in the STL is to use find to find an 
element 
and then erase to remove it. remove in std.container is doing the same thing. 
The problem is that you can't give the result of find to remove, because 
instead 
of a single iterator, find gives you a whole range, and you probably don't want 
to remove that whole range. You generally either want to remove the first 
element 
or some set of elements at the front of the range. So, you need to able to 
remove the other elements from the range so that you can give that range to the 
remove method on the container. That's fine in principle, but since so many of 
the range-based algorithms give you a new type back and you need the exact type 
that that container uses for its ranges, it's very hard to get a range of the 
correct type with the correct elements in it.

So, while find will give you the beginning of the range you want, there's not 
an 
easy way to remove the end of that range. Functions like take and takeExactly 
return new types, so they don't work. The more I look at it, the more I'm 
convinced that we really need to add a primitive to forward ranges that returns 
the first n elements of that range. Without that, I don't see how you can get a 
range of the correct type with only those elements in it unless it's also a 
bidirectional range, which some ranges (like SList's range) aren't.

- Jonathan M Davis

Reply via email to