Thread overview
drop* and take* only for specific element values
Aug 13, 2014
Nordlöw
Aug 13, 2014
Meta
Aug 13, 2014
Jonathan M Davis
Aug 13, 2014
Nordlöw
Aug 13, 2014
Nordlöw
Aug 14, 2014
Jonathan M Davis
Aug 14, 2014
Nordlöw
Aug 16, 2014
monarch_dodra
Aug 13, 2014
Jonathan M Davis
August 13, 2014
Are there variants of drop* and take* that only drop element if its equal to a value kind of like strip does?

If not I believe they should be added.
August 13, 2014
On Wednesday, 13 August 2014 at 12:37:34 UTC, Nordlöw wrote:
> Are there variants of drop* and take* that only drop element if its equal to a value kind of like strip does?
>
> If not I believe they should be added.

No, but it'd probably be useful. Maybe call them dropIf/takeIf, or just add an overload that takes a predicate... I'll look into making a pull request sometime this week. How do you envision these working?
August 13, 2014
On Wed, 13 Aug 2014 14:28:29 +0000
Meta via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com> wrote:

> On Wednesday, 13 August 2014 at 12:37:34 UTC, Nordlöw wrote:
> > Are there variants of drop* and take* that only drop element if its equal to a value kind of like strip does?
> >
> > If not I believe they should be added.
>
> No, but it'd probably be useful. Maybe call them dropIf/takeIf, or just add an overload that takes a predicate... I'll look into making a pull request sometime this week. How do you envision these working?

They're called find and until. You just have to give them the opposite predicate that you'd give a function called dropIf or takeIf.

- Jonathan M Davis

August 13, 2014
On Wed, 13 Aug 2014 07:45:17 -0700
Jonathan M Davis via Digitalmars-d-learn
<digitalmars-d-learn@puremagic.com> wrote:

> On Wed, 13 Aug 2014 14:28:29 +0000
> Meta via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com>
> wrote:
>
> > On Wednesday, 13 August 2014 at 12:37:34 UTC, Nordlöw wrote:
> > > Are there variants of drop* and take* that only drop element if its equal to a value kind of like strip does?
> > >
> > > If not I believe they should be added.
> >
> > No, but it'd probably be useful. Maybe call them dropIf/takeIf, or just add an overload that takes a predicate... I'll look into making a pull request sometime this week. How do you envision these working?
>
> They're called find and until. You just have to give them the opposite predicate that you'd give a function called dropIf or takeIf.

I should probably pointed out that we attempted to put dropWhile and takeWhile into Phobos quite some time ago (which would basically be dropIf and takeIf), but Andrei refused to let them in, because all they did was reverse the predicate, so arguments that they should be added based on the fact that find and until take the opposite predicate aren't going to fly.

- Jonathan M Davis

August 13, 2014
On Wednesday, 13 August 2014 at 14:45:43 UTC, Jonathan M Davis via Digitalmars-d-learn wrote:
> They're called find and until. You just have to give them the opposite
> predicate that you'd give a function called dropIf or takeIf.

Ok, thx.

As an exercise I tried

auto dropWhile(R, E)(R range, E element) if (isInputRange!R &&
                                             is(ElementType!R == E))
{
    import std.algorithm: find;
    return range.find(a => a != element);
}

unittest { dln([1, 2, 3].dropWhile(1)); }

but it errors as

algorithm_ex.d(1452,22): Error: template std.algorithm.find cannot deduce function from argument types !()(int[], void), candidates are:
/home/per/opt/x86_64-unknown-linux-gnu/dmd/linux/bin64/src/phobos/std/algorithm.d(4261,12):        std.algorithm.find(alias pred = "a == b", InputRange, Element)(InputRange haystack, Element needle) if (isInputRange!InputRange && is(typeof(binaryFun!pred(haystack.front, needle)) : bool))
/home/per/opt/x86_64-unknown-linux-gnu/dmd/linux/bin64/src/phobos/std/algorithm.d(4541,4):        std.algorithm.find(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle) if (isForwardRange!R1 && isForwardRange!R2 && is(typeof(binaryFun!pred(haystack.front, needle.front)) : bool) && !isRandomAccessRange!R1)
/home/per/opt/x86_64-unknown-linux-gnu/dmd/linux/bin64/src/phobos/std/algorithm.d(4589,4):        std.algorithm.find(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle) if (isRandomAccessRange!R1 && isBidirectionalRange!R2 && is(typeof(binaryFun!pred(haystack.front, needle.front)) : bool))
/home/per/opt/x86_64-unknown-linux-gnu/dmd/linux/bin64/src/phobos/std/algorithm.d(4661,4):        std.algorithm.find(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle) if (isRandomAccessRange!R1 && isForwardRange!R2 && !isBidirectionalRange!R2 && is(typeof(binaryFun!pred(haystack.front, needle.front)) : bool))
/home/per/opt/x86_64-unknown-linux-gnu/dmd/linux/bin64/src/phobos/std/algorithm.d(4887,23):        std.algorithm.find(alias pred = "a == b", Range, Ranges...)(Range haystack, Ranges needles) if (Ranges.length > 1 && is(typeof(startsWith!pred(haystack, needles))))
algorithm_ex.d(1452,22):        ... (2 more, -v to show) ...
algorithm_ex.d(1456,35): Error: template instance algorithm_ex.dropWhile!(int[], int) error instantiating
/home/per/Work/justd/msgpack.d(4614,25): Warning: calling msgpack.pack!(false, string).pack without side effects discards return value of type ubyte[], prepend a cast(void) if intentional
/home/per/Work/justd/msgpack.d(4614,25): Warning: calling msgpack.pack!(false, string).pack without side effects discards return value of type ubyte[], prepend a cast(void) if intentional

What have I done wrong?
August 13, 2014
On Wednesday, 13 August 2014 at 21:22:31 UTC, Nordlöw wrote:
> unittest { dln([1, 2, 3].dropWhile(1)); }

should be

unittest { [1, 2, 3].dropWhile(1) == [2, 3]; }
August 14, 2014
On Wednesday, 13 August 2014 at 21:22:31 UTC, Nordlöw wrote:
>     return range.find(a => a != element);
> What have I done wrong?

You forgot the !, making the predicate a function argument. It should be

    return range.find!(a => a != element);

- Jonathan M Davis
August 14, 2014
On Thursday, 14 August 2014 at 00:56:47 UTC, Jonathan M Davis wrote:
> You forgot the !, making the predicate a function argument. It

Great!

My solution:

auto dropWhile(R, E)(R range, E element) if (isInputRange!R &&
                                             is(ElementType!R == E))
{
    import std.algorithm: find;
    return range.find!(a => a != element);
}

unittest
{
    assert([1, 2, 3].dropWhile(1) == [2, 3]);
    assert([1, 1, 1, 2, 3].dropWhile(1) == [2, 3]);
    assert([1, 2, 3].dropWhile(2) == [1, 2, 3]);
    assert("abc".dropWhile(cast(dchar)'a') == "bc");
}
August 16, 2014
On Thursday, 14 August 2014 at 07:30:59 UTC, Nordlöw wrote:
> On Thursday, 14 August 2014 at 00:56:47 UTC, Jonathan M Davis wrote:
>> You forgot the !, making the predicate a function argument. It
>
> Great!
>
> My solution:

Depending on your exact needs, don't forget too about "findSkip" (same as find, but skips found element), as well as filter.

In particular, r.filter!pred.take(N) would give you a (lazy) range consisting of the first 10 elements in r that verify pred. In some cases, "until" could also suit your needs.

Long story short, D range and algorithms are little building blocks. There aren't that many "basic" functions that can't simply be expressed as a combination of already existing blocks.