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[]); | ||||
| } | ||||
|   | ||||
| @@ -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); | ||||
|     } | ||||
|  | ||||
|     /// | ||||
|   | ||||
| @@ -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); | ||||
|     } | ||||
|  | ||||
|     /// | ||||
|   | ||||
		Reference in New Issue
	
	Block a user