Meta:
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, " "));
I'd like something like this in Phobos, but I'd like it to have a
better name. But in most (all?) cases what I want to put inside
such perform is a printing function, so I have opened this:
http://d.puremagic.com/issues/show_bug.cgi?id=9882
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;
I's also like this in Phobos, for debugging purposes. But I'd
like it to return nothing, so you are forced to use it only at
the end of a chain.
(So I appreciate 2 of your 4 proposals. I have proposed both of
them in D.learn time ago.)
---------------------
Brad Anderson:
Andrei didn't care for the tap() you propose but loved the idea
of a tap() function that works like unix tee.
Something like this Python itertool?
def tee(iterable, n=2):
it = iter(iterable)
deques = [collections.deque() for i in range(n)]
def gen(mydeque):
while True:
if not mydeque: # when the local deque is
empty
newval = next(it) # fetch a new value and
for d in deques: # load it to all the
deques
d.append(newval)
yield mydeque.popleft()
return tuple(gen(d) for d in deques)
Bye,
bearophile