reduce

Implements the homonym function (also known as accumulate, compress, inject, or foldl) present in various programming languages of functional flavor. There is also fold which does the same thing but with the opposite parameter order. The call reduce!(fun)(seed, range) first assigns seed to an internal variable result, also called the accumulator. Then, for each element x in range, result = fun(result, x) gets evaluated. Finally, result is returned. The one-argument version reduce!(fun)(range) works similarly, but it uses the first element of the range as the seed (the range must be non-empty).

  1. auto reduce(R r)
    template reduce(fun...)
    reduce
    (
    R
    )
    (
    R r
    )
    if (
    isIterable!R
    )
    if (
    fun.length >= 1
    )
  2. auto reduce(S seed, R r)

Members

Functions

reduce
auto reduce(R r)

No-seed version. The first element of r is used as the seed's value.

reduce
auto reduce(S seed, R r)

Seed version. The seed should be a single value if fun is a single function. If fun is multiple functions, then seed should be a std.typecons.Tuple, with one field per function in f.

Parameters

fun

one or more functions

Return Value

the accumulated result

Examples

Many aggregate range operations turn out to be solved with reduce quickly and easily. The example below illustrates reduce's remarkable power and flexibility.

1 import std.algorithm.comparison : max, min;
2 import std.math : approxEqual;
3 import std.range;
4 
5 int[] arr = [ 1, 2, 3, 4, 5 ];
6 // Sum all elements
7 auto sum = reduce!((a,b) => a + b)(0, arr);
8 assert(sum == 15);
9 
10 // Sum again, using a string predicate with "a" and "b"
11 sum = reduce!"a + b"(0, arr);
12 assert(sum == 15);
13 
14 // Compute the maximum of all elements
15 auto largest = reduce!(max)(arr);
16 assert(largest == 5);
17 
18 // Max again, but with Uniform Function Call Syntax (UFCS)
19 largest = arr.reduce!(max);
20 assert(largest == 5);
21 
22 // Compute the number of odd elements
23 auto odds = reduce!((a,b) => a + (b & 1))(0, arr);
24 assert(odds == 3);
25 
26 // Compute the sum of squares
27 auto ssquares = reduce!((a,b) => a + b * b)(0, arr);
28 assert(ssquares == 55);
29 
30 // Chain multiple ranges into seed
31 int[] a = [ 3, 4 ];
32 int[] b = [ 100 ];
33 auto r = reduce!("a + b")(chain(a, b));
34 assert(r == 107);
35 
36 // Mixing convertible types is fair game, too
37 double[] c = [ 2.5, 3.0 ];
38 auto r1 = reduce!("a + b")(chain(a, b, c));
39 assert(approxEqual(r1, 112.5));
40 
41 // To minimize nesting of parentheses, Uniform Function Call Syntax can be used
42 auto r2 = chain(a, b, c).reduce!("a + b");
43 assert(approxEqual(r2, 112.5));

Sometimes it is very useful to compute multiple aggregates in one pass. One advantage is that the computation is faster because the looping overhead is shared. That's why reduce accepts multiple functions. If two or more functions are passed, reduce returns a std.typecons.Tuple object with one member per passed-in function. The number of seeds must be correspondingly increased.

1 import std.algorithm.comparison : max, min;
2 import std.math : approxEqual, sqrt;
3 import std.typecons : tuple, Tuple;
4 
5 double[] a = [ 3.0, 4, 7, 11, 3, 2, 5 ];
6 // Compute minimum and maximum in one pass
7 auto r = reduce!(min, max)(a);
8 // The type of r is Tuple!(int, int)
9 assert(approxEqual(r[0], 2));  // minimum
10 assert(approxEqual(r[1], 11)); // maximum
11 
12 // Compute sum and sum of squares in one pass
13 r = reduce!("a + b", "a + b * b")(tuple(0.0, 0.0), a);
14 assert(approxEqual(r[0], 35));  // sum
15 assert(approxEqual(r[1], 233)); // sum of squares
16 // Compute average and standard deviation from the above
17 auto avg = r[0] / a.length;
18 auto stdev = sqrt(r[1] / a.length - avg * avg);

See Also

Fold (higher-order function)

fold is functionally equivalent to reduce with the argument order reversed, and without the need to use tuple for multiple seeds. This makes it easier to use in UFCS chains.

sum is similar to reduce!((a, b) => a + b) that offers pairwise summing of floating point numbers.

Meta