summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2019-04-17 06:27:18 +0200
committerEugen Wissner <belka@caraus.de>2019-04-17 06:27:18 +0200
commit76bda0ac8df2f9e5d49e126d16d785f5c63c4430 (patch)
tree9fef4f9163c92eadc854501b76587924cdd62179 /source
parentf214f3baa2f3b613f39ded5ac615a887603aa05c (diff)
downloadtanya-76bda0ac8df2f9e5d49e126d16d785f5c63c4430.tar.gz
Add getAndPopFront()/getAndPopBack()
Diffstat (limited to 'source')
-rw-r--r--source/tanya/algorithm/iteration.d5
-rw-r--r--source/tanya/container/array.d8
-rw-r--r--source/tanya/range/primitive.d94
3 files changed, 98 insertions, 9 deletions
diff --git a/source/tanya/algorithm/iteration.d b/source/tanya/algorithm/iteration.d
index 0e91c5d..e71d581 100644
--- a/source/tanya/algorithm/iteration.d
+++ b/source/tanya/algorithm/iteration.d
@@ -756,7 +756,7 @@ if (F.length == 1)
*
* 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 (range.empty)
@@ -765,8 +765,7 @@ if (F.length == 1)
}
else
{
- auto acc = F[0](init, range.front);
- range.popFront;
+ auto acc = F[0](init, getAndPopFront(range));
return foldl(range, acc);
}
}
diff --git a/source/tanya/container/array.d b/source/tanya/container/array.d
index 5b3f522..872d55e 100644
--- a/source/tanya/container/array.d
+++ b/source/tanya/container/array.d
@@ -16,6 +16,7 @@ module tanya.container.array;
import core.checkedint;
import tanya.algorithm.comparison;
+import tanya.algorithm.iteration;
import tanya.algorithm.mutation;
import tanya.memory.allocator;
import tanya.memory.lifetime;
@@ -670,12 +671,7 @@ struct Array(T)
{
reserve(length + el.length);
}
- size_t retLength;
- foreach (e; el)
- {
- retLength += insertBack(e);
- }
- return retLength;
+ return foldl!((acc, e) => acc + insertBack(e))(el, 0U);
}
/// ditto
diff --git a/source/tanya/range/primitive.d b/source/tanya/range/primitive.d
index 82950ac..258d5d5 100644
--- a/source/tanya/range/primitive.d
+++ b/source/tanya/range/primitive.d
@@ -1545,3 +1545,97 @@ if (isInputRange!Range && hasLvalueElements!Range)
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);
+}