Should we add drop to Phobos?

Timon Gehr timon.gehr at gmx.ch
Sun Aug 14 04:09:59 PDT 2011


On 08/14/2011 08:02 AM, Jonathan M Davis wrote:
> Okay. Right now, if you want to remove n elements from the front of a range,
> you use popFrontN.
>
> popFrontN(range, n);
>
> This is obviously a highly useful function. However, it does not work very
> well when chaining range-based functions. For instance, what if you need to
> call find on a range, but you know that what you're looking for is not in the
> first n elements of that range? You'd do
>
> popFrontN(range, n);
> auto found = find(range, needle);
>
> And what if you don't want to alter the range when you did that? You'd do
> something like
>
> auto toFind = range.save;
> toFind.popFrontN(range, n);
> auto found = find(toFind, needle);
>
> That's not very functional at all and requires multiple lines of code. Also,
> if you want to chain more than one function and need to call popFrontN
> multiple times in there, you can't chain them very well. popFrontN returns the
> actual number of elements popped, not the range, so you can't just pass its
> result into another range-based function.
>
> However, if you had a drop function, you could do this
>
> auto found = find(drop(range, n), needle);
>
> You now only have one line of code instead of three. And if you have more
> complicated chaining, it's that much more useful. However, it does have one
> downside.
>
> Both popFrontN and drop pop _up to_ n elements, so if there are fewer than n
> elements in the range, then as many elements as are in the range are popped.
> However, in the case of popFrontN, it returns the actual number of elements
> popped, so you know how many elements were popped. drop, on the other hand,
> returns the range with the elements popped, so you don't know how many
> elements were popped unless you do something like
>
> auto newRange = drop(range, n);
> auto elementsDropped = newRange.empty ? walkLength(range) : n;
>
> Also, drop doesn't alter the original range, so if you call it multiple times
> on the same range instead of using popFrontN, then it's inefficient. However,
> it's not like we're getting rid of popFrontN, so if that's an issue, you can
> just call popFrontN instead. It's just up to the progammer to decide which is
> best for what they're doing. In cases where you want to chain range-based
> functions and don't want to alter the original range, drop is best. In cases
> where you want to alter the original range and don't necessarily care about
> chaining functions, popFrontN is best.
>
> Now, as Andrei has pointed out, you can get a similar effect by doing
> (popFrontN(range, n), range). So, instead of
>
> auto found = find(drop(range, n), needle);
>
> you can do something like
>
> auto found = find((popFrontN(range, n), range), needle);
>
> However, that involves the comma operator, which most people avoid. It also
> alters the original range instead of returning a new one with n elements
> popped off, though whether that's good or bad depends on what you're doing.
>
> So, the question is: Is drop worth having in Phobos? It's common in functional
> languages, and if you want to program in a more functional style, it's of
> enormous benefit. We'll still have popFrontN regardless, so the question is
> whether drop adds enough value to be worth having or whether it's just too
> similar to popFrontN to be worth adding to the standard library.
>
> Personally, I think that drop would be a _very_ useful function to have. What
> do you think?
>
> - Jonathan M Davis

+1. Having take but not drop does not add to the beauty of the module. 
I'm also strongly in favor of adding dropWhile, dropUntil and takeWhile, 
plus renaming std.algorithm.until to takeUntil. "until" is an 
undescriptive name and it has a different meaning in functional 
programming language libraries.


More information about the Digitalmars-d mailing list