Add getAndPopFront()/getAndPopBack()

This commit is contained in:
Eugen Wissner 2019-04-17 06:27:18 +02:00
parent f214f3baa2
commit 76bda0ac8d
3 changed files with 98 additions and 9 deletions

View File

@ -756,7 +756,7 @@ if (F.length == 1)
* *
* Returns: Accumulated value. * Returns: Accumulated value.
*/ */
T foldl(R, T)(R range, auto ref T init) auto foldl(R, T)(R range, auto ref T init)
if (isInputRange!R && !isInfinite!R) if (isInputRange!R && !isInfinite!R)
{ {
if (range.empty) if (range.empty)
@ -765,8 +765,7 @@ if (F.length == 1)
} }
else else
{ {
auto acc = F[0](init, range.front); auto acc = F[0](init, getAndPopFront(range));
range.popFront;
return foldl(range, acc); return foldl(range, acc);
} }
} }

View File

@ -16,6 +16,7 @@ module tanya.container.array;
import core.checkedint; import core.checkedint;
import tanya.algorithm.comparison; import tanya.algorithm.comparison;
import tanya.algorithm.iteration;
import tanya.algorithm.mutation; import tanya.algorithm.mutation;
import tanya.memory.allocator; import tanya.memory.allocator;
import tanya.memory.lifetime; import tanya.memory.lifetime;
@ -670,12 +671,7 @@ struct Array(T)
{ {
reserve(length + el.length); reserve(length + el.length);
} }
size_t retLength; return foldl!((acc, e) => acc + insertBack(e))(el, 0U);
foreach (e; el)
{
retLength += insertBack(e);
}
return retLength;
} }
/// ditto /// ditto

View File

@ -1545,3 +1545,97 @@ if (isInputRange!Range && hasLvalueElements!Range)
assert(!sameHead(r1, r2)); assert(!sameHead(r1, r2));
} }
/**
* Returns the first element and advances the range.
*
* If $(D_PARAM range) has lvalue elements, then $(D_PSYMBOL getAndPopFront)
* returns by reference, otherwise the returned element is copied.
*
* Params:
* R = Input range type.
* range = Input range.
*
* Returns: Front range element.
*
* See_Also: $(D_PSYMBOL getAndPopBack).
*/
ElementType!R getAndPopFront(R)(ref R range)
if (isInputRange!R)
in (!range.empty)
{
static if (hasLvalueElements!R)
{
auto el = (() @trusted => &range.front())();
}
else
{
auto el = range.front;
}
range.popFront();
static if (hasLvalueElements!R)
{
return *el;
}
else
{
return el;
}
}
///
@nogc nothrow pure @safe unittest
{
int[3] array = [1, 2, 3];
auto slice = array[];
assert(getAndPopFront(slice) == 1);
assert(slice.length == 2);
}
/**
* Returns the last element and removes it from the range.
*
* If $(D_PARAM range) has lvalue elements, then $(D_PSYMBOL getAndPopBack)
* returns by reference, otherwise the returned element is copied.
*
* Params:
* R = Bidirectional range type.
* range = Bidirectional range.
*
* Returns: Last range element.
*
* See_Also: $(D_PSYMBOL getAndPopFront).
*/
auto ref getAndPopBack(R)(ref R range)
if (isBidirectionalRange!R)
in (!range.empty)
{
static if (hasLvalueElements!R)
{
auto el = (() @trusted => &range.back())();
}
else
{
auto el = range.back;
}
range.popBack();
static if (hasLvalueElements!R)
{
return *el;
}
else
{
return el;
}
}
///
@nogc nothrow pure @trusted unittest
{
int[3] array = [1, 2, 3];
auto slice = array[];
assert(getAndPopBack(slice) == 3);
assert(slice.length == 2);
}