Last time, I wrote an article briefly introducing functional thinking. My classmate was very interested after reading it and hoped that I could write more about it when I was free. Then he said that he could think of using array map, but not reduce. I think this may also be a common phenomenon, because for students who are not familiar with FP (functional programming), the impression of Map in their mind may be basically equivalent to loop, while reduce is relatively unfamiliar. However, reduce is a more general function than map, flatMap, etc., and you can easily implement other functions with Reduce.

Let’s implement reduce first:

const reduce = (reducer, acc) = > list => {
    const [head, ...rest] = list;
    if (head === undefined) return acc;

    return reduce(reducer, reducer(acc, head))(rest);
};
Copy the code

Array.prototype.reduce in JS is slightly different from mine. Its reducer can receive four parameters (more currentIndex and Array than my version). Tell us that it is most likely to be implemented through a loop. To be honest, I feel that the latter two parameters are basically useless, and other languages generally do not have these two parameters.

Then explain why, instead of taking three arguments directly, my Reduce takes two and returns a function that takes one argument in partial application form. Sum sum sum sum sum sum sum sum sum sum sum

const arr = [1.2.3]; // All the following arRs are the same

const sum = reduce((acc, x) = > acc + x, 0);
sum(arr); / / = > 6
Copy the code

Reduce will return different functions when receiving different Reducer and ACC. Here sum is returned, which is very smooth. If reduce is a function that takes three arguments, then sum must be const sum = (arr) => reduce((acc, x) => ACC + x, 0, arr), not impossible, but ugly.

Next we use Reduce to implement other array methods: Length, map, flatMap, includes, and find

// JS array. length is not the same as my implementation,
// arr[100] = 1, arr. Length = 101, because JS is an Array of objects
const length = reduce(acc= > acc + 1.0);
length(arr); / / = > 3

const map = func= > reduce((acc, x) = > [...acc, func(x)], []);
map(x= > x + 1)(arr); // => [2, 3, 4]

const flatMap = func= > reduce((acc, x) = > [...acc, ...func(x)], []);
flatMap(x= > [x + 1])(arr); // => [2, 3, 4]

const includes = element= > reduce((acc, x) = > acc || (x === element), false);
includes(1)(arr); // => true

// return the first element that matches the condition, otherwise return undefined
const find = func= > reduce((acc, x) = > acc || (func(x) ? x : undefined), undefined);
find(x= > x > 2)(arr); / / = > 3
Copy the code

String. Prototype: String. Prototype: String.

// string
String.prototype.reduce = function (reducer, acc) {
    return reduce(reducer, acc)(this.split(' '));
};

String.prototype.map = function (func) {
    return map(func)(this.split(' ')).join(' ');
};

const str = '123';
str.reduce((acc, x) = > acc + Number(x), 0); / / = > 6
str.map(x= > Number(x) + 1); / / = > '234'
Copy the code

Emmmmmmm… That’s it.