From f491d1f23389cb348cc8bbacf3d2d68b80f8ad85 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Mon, 30 Oct 2023 16:14:10 +0000 Subject: [PATCH 1/4] [std.algorithm] Improve `fold` docs Mention iteratively calling predicates in summary. Use list to explain calling a single predicate with a seed. Mention multiple results are produced in description. Use list for see also. Rename `seed` parameter `seeds` and fix docs. Fix result docs when >1 predicate. --- std/algorithm/iteration.d | 43 +++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/std/algorithm/iteration.d b/std/algorithm/iteration.d index 39927be9bbb..c9336c5189f 100644 --- a/std/algorithm/iteration.d +++ b/std/algorithm/iteration.d @@ -4809,26 +4809,34 @@ private template ReduceSeedType(E) /++ Implements the homonym function (also known as `accumulate`, $(D compress), `inject`, or `foldl`) present in various programming -languages of functional flavor. The call `fold!(fun)(range, seed)` -first assigns `seed` to an internal variable `result`, -also called the accumulator. Then, for each element `x` in $(D -range), `result = fun(result, x)` gets evaluated. Finally, $(D -result) is returned. The one-argument version `fold!(fun)(range)` +languages of functional flavor, iteratively calling one or more predicates. + +$(P For a single predicate, +the call `fold!(fun)(range, seed)` will:) + +* Assign `seed` to an internal variable `result` (also called the accumulator) +* For each element `e` in $(D range), evaluate `result = fun(result, e)`. +* Return $(D result). + +$(P The one-argument version `fold!(fun)(range)` works similarly, but it uses the first element of the range as the -seed (the range must be non-empty). +seed (the range must be non-empty) and iterates over the remaining +elements.) + +Multiple results are produced when using multiple predicates. Params: fun = the predicate function(s) to apply to the elements See_Also: - $(HTTP en.wikipedia.org/wiki/Fold_(higher-order_function), Fold (higher-order function)) + * $(HTTP en.wikipedia.org/wiki/Fold_(higher-order_function), Fold (higher-order function)) - $(LREF sum) is similar to `fold!((a, b) => a + b)` that offers - precise summing of floating point numbers. + * $(LREF sum) is similar to `fold!((a, b) => a + b)` that offers + precise summing of floating point numbers. - This is functionally equivalent to $(LREF reduce) with the argument order - reversed, and without the need to use $(REF_ALTTEXT `tuple`,tuple,std,typecons) - for multiple seeds. + * `fold` is functionally equivalent to $(LREF reduce) with the argument order + reversed, and without the need to use $(REF_ALTTEXT `tuple`,tuple,std,typecons) + for multiple seeds. +/ template fold(fun...) if (fun.length >= 1) @@ -4836,20 +4844,21 @@ if (fun.length >= 1) /** Params: r = the $(REF_ALTTEXT input range, isInputRange, std,range,primitives) to fold - seed = the initial value of the accumulator + seeds = the initial values of each accumulator (optional), one for each predicate Returns: - the accumulated `result` + Either the accumulated result for a single predicate, or a + $(REF_ALTTEXT `Tuple`,Tuple,std,typecons) of results. */ - auto fold(R, S...)(R r, S seed) + auto fold(R, S...)(R r, S seeds) { static if (S.length < 2) { - return reduce!fun(seed, r); + return reduce!fun(seeds, r); } else { import std.typecons : tuple; - return reduce!fun(tuple(seed), r); + return reduce!fun(tuple(seeds), r); } } } From 5762f3311b3ad9c47638d60bd57e40374c875088 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Tue, 31 Oct 2023 17:26:48 +0000 Subject: [PATCH 2/4] Explain predicate signature --- std/algorithm/iteration.d | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/std/algorithm/iteration.d b/std/algorithm/iteration.d index c9336c5189f..4af78918705 100644 --- a/std/algorithm/iteration.d +++ b/std/algorithm/iteration.d @@ -4811,6 +4811,12 @@ Implements the homonym function (also known as `accumulate`, $(D compress), `inject`, or `foldl`) present in various programming languages of functional flavor, iteratively calling one or more predicates. +$(P Each predicate in `fun` must take two arguments:) +* An accumulator value +* An element of the range `r` +$(P Each predicate must return a value which implicitly converts to the +type of the accumulator.) + $(P For a single predicate, the call `fold!(fun)(range, seed)` will:) From 2170bb37bc3738b237a7698ff29570f0b60483f7 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Tue, 31 Oct 2023 17:37:05 +0000 Subject: [PATCH 3/4] Tweak seed description --- std/algorithm/iteration.d | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/std/algorithm/iteration.d b/std/algorithm/iteration.d index 4af78918705..b0d890fd7b4 100644 --- a/std/algorithm/iteration.d +++ b/std/algorithm/iteration.d @@ -4820,7 +4820,8 @@ type of the accumulator.) $(P For a single predicate, the call `fold!(fun)(range, seed)` will:) -* Assign `seed` to an internal variable `result` (also called the accumulator) +* Use `seed` to initialize an internal variable `result` (also called + the accumulator). * For each element `e` in $(D range), evaluate `result = fun(result, e)`. * Return $(D result). From 7f06f2358afc3c4028274978074c59cea6b1c1d2 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Tue, 31 Oct 2023 17:40:45 +0000 Subject: [PATCH 4/4] Rename `b` to `e` for element in predicates --- std/algorithm/iteration.d | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/std/algorithm/iteration.d b/std/algorithm/iteration.d index b0d890fd7b4..fdd27246051 100644 --- a/std/algorithm/iteration.d +++ b/std/algorithm/iteration.d @@ -4876,10 +4876,10 @@ if (fun.length >= 1) immutable arr = [1, 2, 3, 4, 5]; // Sum all elements - assert(arr.fold!((a, b) => a + b) == 15); + assert(arr.fold!((a, e) => a + e) == 15); // Sum all elements with explicit seed - assert(arr.fold!((a, b) => a + b)(6) == 21); + assert(arr.fold!((a, e) => a + e)(6) == 21); import std.algorithm.comparison : min, max; import std.typecons : tuple; @@ -4891,10 +4891,10 @@ if (fun.length >= 1) assert(arr.fold!(min, max)(0, 7) == tuple(0, 7)); // Can be used in a UFCS chain - assert(arr.map!(a => a + 1).fold!((a, b) => a + b) == 20); + assert(arr.map!(a => a + 1).fold!((a, e) => a + e) == 20); // Return the last element of any range - assert(arr.fold!((a, b) => b) == 5); + assert(arr.fold!((a, e) => e) == 5); } @safe @nogc pure nothrow unittest