Add algorithm.iteration.foldr
This commit is contained in:
@ -779,3 +779,63 @@ if (F.length == 1)
|
||||
|
||||
assert(actual == 6);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accumulates all elements of a range using a function.
|
||||
*
|
||||
* $(D_PSYMBOL foldr) takes a function, an input range and the initial value.
|
||||
* The function takes this initial value and the first element of the range (in
|
||||
* this order), puts them together and returns the result. The return
|
||||
* type of the function should be the same as the type of the initial value.
|
||||
* This is than repeated for all the remaining elements of the range, whereby
|
||||
* the value returned by the passed function is used at the place of the
|
||||
* initial value.
|
||||
*
|
||||
* $(D_PSYMBOL foldr) accumulates from right to left.
|
||||
*
|
||||
* Params:
|
||||
* F = Callable accepting the accumulator and a range element.
|
||||
*/
|
||||
template foldr(F...)
|
||||
if (F.length == 1)
|
||||
{
|
||||
/**
|
||||
* Params:
|
||||
* R = Bidirectional range type.
|
||||
* T = Type of the accumulated value.
|
||||
* range = Bidirectional range.
|
||||
* init = Initial value.
|
||||
*
|
||||
* Returns: Accumulated value.
|
||||
*/
|
||||
auto foldr(R, T)(R range, auto ref T init)
|
||||
if (isBidirectionalRange!R)
|
||||
{
|
||||
if (range.empty)
|
||||
{
|
||||
return init;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto acc = F[0](init, getAndPopBack(range));
|
||||
return foldr(range, acc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
int[3] range = [1, 2, 3];
|
||||
int[3] output;
|
||||
const int[3] expected = [3, 2, 1];
|
||||
|
||||
alias f = (acc, x) {
|
||||
acc.front = x;
|
||||
acc.popFront;
|
||||
return acc;
|
||||
};
|
||||
const actual = foldr!f(range[], output[]);
|
||||
|
||||
assert(output[] == expected[]);
|
||||
}
|
||||
|
Reference in New Issue
Block a user