A Small Contribution to Phobos
Meta
jared771 at gmail.com
Sat Jun 1 19:57:53 PDT 2013
I saw a thread a few days ago about somebody wanting a few
UFCS-based convenience functions, so I thought that I'd take the
opportunity to make a small contribution to Phobos. Currently I
have four small functions: each, exhaust, perform, and tap, and
would like some feedback.
each is designed to perform operations with side-effects on each
range element. To actually change the elements of the range, each
element must be accepted by reference.
Range each(alias fun, Range)(Range r)
if (isInputRange!(Unqual!Range))
{
alias unaryFun!fun _fun;
foreach (ref e; r)
{
fun(e);
}
return r;
}
//Prints [-1, 0, 1]
[1, 2, 3].each!((ref i) => i -= 2).writeln;
exhaust iterates a range until it is exhausted. It also has the
nice feature that if range.front is callable, exhaust will call
it upon each iteration.
Range exhaust(Range)(Range r)
if (isInputRange!(Unqual!Range))
{
while (!r.empty)
{
r.front();
r.popFront();
}
return r;
}
//Writes "www.dlang.org". x is an empty MapResult range.
auto x = "www.dlang.org"
.map!((c) { c.write; return false; })
.exhaust;
//Prints []
[1, 2, 3].exhaust.writeln;
perform is pretty badly named, but I couldn't come up with a
better one. It can be inserted in a UFCS chain and perform some
operation with side-effects. It doesn't alter its argument, just
returns it for the next function in the chain.
T perform(alias dg, T)(ref T val)
{
dg();
return val;
}
//Prints "Mapped: 2 4"
[1, 2, 3, 4, 5]
.filter!(n => n < 3)
.map!(n => n * n)
.perform!({write("Mapped: ");})
.each!(n => write(n, " "));
Lastly is tap, which takes a value and performs some mutating
operation on it. It then returns the value.
T tap(alias dg, T)(auto ref T val)
{
dg(val);
return val;
}
class Foo
{
int x;
int y;
}
auto f = (new Foo).tap!((f)
{
f.x = 2;
f.y = 3;
});
//Prints 2 3
writeln(f.x, " ", f.y);
struct Foo2
{
int x;
int y;
}
//Need to use ref for value types
auto f2 = Foo2().tap!((ref f)
{
f.x = 3;
f.y = 2;
});
//Prints 3 2
writeln(f2.x, " ", f2.y);
Do you think these small functions have a place in Phobos? I
think each and exhaust would be best put into std.range, but I'm
not quite sure where perform and tap should go. Also, there's
that horrible name for perform, for which I would like to come up
with a better name.
More information about the Digitalmars-d
mailing list