www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 12592] New: std.algorithm.keep?

https://issues.dlang.org/show_bug.cgi?id=12592

          Issue ID: 12592
           Summary: std.algorithm.keep?
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Severity: enhancement
          Priority: P1
         Component: Phobos
          Assignee: nobody puremagic.com
          Reporter: bearophile_hugs eml.cc

This code uses ranges in a UFCS chain to compute the unique items of immutable
data items, and to return an array (if you don't need r to be an array you can
omit the last 'array' call):

void main() {
    import std.array: array;
    import std.algorithm: sort, uniq, map;
    immutable data = [10, 3, 2, 3, 4, 10];
    const int[] r = data.dup.sort().uniq.array;
    assert(r == [2, 3, 4, 10]);
}


But that allocates two arrays (beside the data), one in 'dup' and one in
'array'. To avoid that you can write:

void main() {
    import std.algorithm: sort, uniq, copy;
    immutable data = [10, 3, 2, 3, 4, 10];
    auto int[] r = data.dup.sort().release;
    r.length -= r.uniq.copy(r).length;
    assert(r == [2, 3, 4, 10]);
}


But:
- This code is not very easy to write correctly the first time (I have had to
compile and run it to be sure);
- Its semantics and purpose are not as immediately clear for the reader as the
first version;
- Now r can't be const;
- We have lost the nice single UFCS chain, and the code is longer.


So a possible solution is to add a new function similar 'uniq' that performs
that common operation (I don't know if release is needed here):

void main() {
    import std.array: array;
    import std.algorithm: sort, uniq, map;
    immutable data = [10, 3, 2, 3, 4, 10];
    const int[] r = data.dup.sort().release.keepUniq;
    assert(r == [2, 3, 4, 10]);
}


But that seems to contain a common pattern that perhaps it's worth
generalizing, a pattern that is equally usable here too:

const int[] r2 = data.dup.sort().filter!(x => x > 3).array;

That could become:

const int[] r2 = data.dup.sort().release.keepFilter!(x => x > 3);


Generalizing it could become:

const int[] r2 = data.dup.sort().release.keep!(filter!(x => x > 3));

And applied on the original code:

const int[] r = data.dup.sort().release.keep!uniq;


Another example:

auto data2 = [10, 3, 2, 3, 4, 10];
data2 = data2.remove!(x => x > 3);
assert(data2 == [3, 2, 3]);


Becomes:

data2.keep!(remove!(x => x > 3));

But this is not a good example because in my opinion it's much better to fix
remove, see issue 10959 .

If you have more usage cases please add them below.

--
Apr 18 2014