On 16.08.2011 23:37, Jonathan M Davis wrote:
On Tuesday, August 16, 2011 14:27:18 Dmitry Olshansky wrote:
On 16.08.2011 6:33, Jonathan M Davis wrote:
On Tuesday, August 16, 2011 04:26:48 Martin Nowak wrote:
I personally like immutable methods way better than a ref changing
function like popFrontN.
As you pointed out writing str.find(";").drop(2).find(";").drop(2) is
cleaner than writing this with popFrontN.
Drop will have issues for input ranges.
No more than many range-based functions do. Yes, it'll alter the input,
that's to be expected with any range-based function that you pass an
input range to. drop could be made to take only a forward range, but
that seems unnecessarily limiting. You just have to be aware of the
fact that range-based functions always remove elements from input
ranges when they process them - either that or they don't work with
input ranges.
Adding a ref count parameter overload to let you know how many
elements
were dropped/not dropped seems too messy. No idea for that one.
It's a tradeoff. And if you really want drop, you probably don't care
anyway, since what you'd be doing would be chaining functions. If you
really care, just use popFrontN.
The documentation should clearly state that this offers similar
functionality to popFrontN but it's purpose
is to enable a different syntax so that people don't get completely
confused.
It does. This is the ddoc comment that I have for it:
/++
Pops $(D n) elements off of the given range and returns it. If
the length of the given range is less than $(D n), then an
empty range is returned. The original range is unaltered as
long as it's a value type.
Shouldn't this be : "as long as it's not an Input range", for everything
else there is this clanky .save()
No, I meant what it says. drop doesn't call save, so it'll work with input
ranges. However, if you use a range which is a class with it, then it's going
to alter the original range.
I was arguing that Input range is always altered no matter if it's
struct or class or whatnot. So if it's used on forward range it should
really call .save (worth a single static if ?) I think, thus avoiding
side effects even if it's class.
For input ranges it becomes equivalent of (r.popFrontN(n), r); with all
side effects as you described.
Seriously, "value type input ranges" are forward ranges, isn't it? (at
least they should be)
Forward ranges which are value types will not
have the original range affected, but both input ranges and forward ranges
which are classes will. I should probably find a better way to say it though to
make it clearer. I suspect that a fair bit of Phobos doesn't work properly
with ranges which are classes though. It's often assumed that passing a range
to a function means that the original won't be altered, which isn't
necessarily true.
Anyway speaking of drop, I like it and don't think it'll cause some
confusion as long as it's documentation clearly shows reasons on drop
vs popFront. And it does in the following statements:
The main reason to use $(D drop) instead of $(LREF popFrontN)
is so that you can pop elements off of a range and pass the
resulting range to another range-based function in a single
expression, allowing you to chain function calls. It allows
for a more functional style of programming. However, this
means that you don't know exactly how many elements were
actually popped in
How about "an efficient thing to do for all ranges" ---> "efficient for
ranges in general"?
the case where the range had fewer than $(D n) elements
(unless you got its length first, which isn't an efficient
thing to do for all ranges).
A little bit of repetition here (you already told it's used to pass
results to functions, etc.)
I'll tweak the language a bit. Thanks.
- Jonathan M Davis
--
Dmitry Olshansky