summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2019-04-24 06:53:08 +0200
committerEugen Wissner <belka@caraus.de>2019-04-24 06:53:08 +0200
commit0a973b46ba399e238324620a6a0b117ec5e510b3 (patch)
tree60aaed466dd8b5d10bf8d1e6a1cc546b4d97c9c7
parent73535568b79a0b124bc1653002637a830ce0fcb8 (diff)
downloadtanya-0a973b46ba399e238324620a6a0b117ec5e510b3.tar.gz
Add algorithm.iteration.foldr
-rw-r--r--source/tanya/algorithm/iteration.d60
-rw-r--r--source/tanya/container/hashtable.d8
-rw-r--r--source/tanya/container/list.d8
3 files changed, 64 insertions, 12 deletions
diff --git a/source/tanya/algorithm/iteration.d b/source/tanya/algorithm/iteration.d
index e71d581..0b1a31c 100644
--- a/source/tanya/algorithm/iteration.d
+++ b/source/tanya/algorithm/iteration.d
@@ -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[]);
+}
diff --git a/source/tanya/container/hashtable.d b/source/tanya/container/hashtable.d
index 2ae18db..349e681 100644
--- a/source/tanya/container/hashtable.d
+++ b/source/tanya/container/hashtable.d
@@ -14,6 +14,7 @@
*/
module tanya.container.hashtable;
+import tanya.algorithm.iteration;
import tanya.algorithm.mutation;
import tanya.container.array;
import tanya.container.entry;
@@ -718,12 +719,7 @@ if (isHashFunction!(hasher, Key))
size_t insert(R)(scope R range)
if (isForwardRange!R && is(ElementType!R == KeyValue) && !isInfinite!R)
{
- size_t count;
- foreach (e; range)
- {
- count += insert(e);
- }
- return count;
+ return foldl!((acc, x) => acc + insert(x))(range, 0U);
}
///
diff --git a/source/tanya/container/list.d b/source/tanya/container/list.d
index c01b863..31ddfd5 100644
--- a/source/tanya/container/list.d
+++ b/source/tanya/container/list.d
@@ -16,6 +16,7 @@
module tanya.container.list;
import tanya.algorithm.comparison;
+import tanya.algorithm.iteration;
import tanya.container.entry;
import tanya.memory.allocator;
import tanya.memory.lifetime;
@@ -1690,12 +1691,7 @@ struct DList(T)
&& isImplicitlyConvertible!(ElementType!R, T))
in (checkRangeBelonging(r))
{
- size_t inserted;
- foreach (e; el)
- {
- inserted += insertAfter(r, e);
- }
- return inserted;
+ return foldl!((acc, x) => acc + insertAfter(r, x))(el, 0U);
}
///