# The meaning of Reduce and Transduce

To learn functional programming , you must master a lot of terms, otherwise you won’t understand the documentation at all.

This article introduces two basic terms: ``` reduce ``` and ``` transduce ``` . They are very important and very useful. ## 1. The usage of reduce

``` reduce ``` It is an array operation, usually used to “accumulate” all the members of an array into one value.

``````
var arr = [1, 2, 3, 4];

var sum = (a, b) => a + b;

arr.reduce(sum, 0) // 10
``````

In the above code, a function is executed on each member ``` reduce ``` of the array . The parameter is a cumulative variable, and the parameter is the current array member. Each time it is executed, it will be added to and finally output . ``` arr ``` ``` sum ``` ``` sum ``` ``` a ``` ``` b ``` ``` b ``` ``` a ``` ``` a ```

The cumulative variable must have an initial value. The above example is ``` reduce ``` the second parameter of the function ``` 0 ``` . If this parameter is omitted, the initial value defaults to the first member of the array.

``````
var arr = [1, 2, 3, 4];

var sum = function (a, b) {
console.log(a, b);
return a + b;
};

arr.reduce(sum) // => 10
// 1 2
// 3 3
// 6 4
``````

In the above code, the ``` reduce ``` method omits the initial value. Through ``` sum ``` the print statement in the function, you can see every change of the accumulated variable.

In short, the ``` reduce ``` method provides a traversal means to “accumulate” all members of the array.

## 2. Map is a special case of reduce

The initial value of the cumulative variable can also be an array.

``````
var arr = [1, 2, 3, 4];

var handler = function (newArr, x) {
newArr.push(x + 1);
return newArr;
};

arr.reduce(handler, [])
// [2, 3, 4, 5]
``````

In the above code, the initial value of the cumulative variable is an empty array, and ``` reduce ``` a new array is returned as a result , which is equivalent to the execution ``` map ``` method, which “transforms” the original array once. The following is ``` map ``` an example of using rewrite the above.

``````
var arr = [1, 2, 3, 4];
var plusOne = x => x + 1;
arr.map(plusOne) // [2, 3, 4, 5]
``````

In fact, all ``` map ``` methods can be based on ``` reduce ``` implementation.

``````
function map(f, arr) {
return arr.reduce(function(result, x) {
result.push(f(x));
return result;
}, []);
}
``````

Therefore, it ``` map ``` is just ``` reduce ``` a special case.

## Three, ``` reduce ``` the essence

Essentially, it ``` reduce ``` is a combination of three operations.

• Traverse
• Deformed
• accumulation

Let’s look at the example above.

``````
var arr = [1, 2, 3, 4];
var handler = function (newArr, x) {
newArr.push(x + 1);
return newArr;
};

arr.reduce(handler, [])
// [2, 3, 4, 5]
``````

In the above code, first, ``` reduce ``` the original array is traversed, which is ``` map ``` the fundamental reason why it can replace the method; second, ``` reduce ``` each member of the original array is “transformed” (addition in the above example ``` 1 ``` ); finally, they are accumulated (The above example is the ``` push ``` method).

## Fourth, the meaning of transduce

``` reduce ``` Contains three operations, so it is very useful. But it also brings a problem: the reusability of the code is not high. In the ``` reduce ``` inside, the deformation and accumulation are coupled, not easy to split.

For each use ``` reduce ``` , developers often have to write code from scratch and repeatedly implement many basic functions. It is difficult to reuse other people’s code.

``````
var handler = function (newArr, x) {
newArr.push(x + 1);
return newArr;
};
``````

The above processing function is difficult to use in other situations.

Is there a solution? The answer is yes, that is, to separate the two operations of “deformation” and “accumulation”. If the ``` reduce ``` transformation operation and accumulation operation are allowed to be separated, the reusability of the code will be greatly increased. This is ``` transduce ``` the origin of the method.

``` transduce ``` The name comes from the combination of the two words transform and reduce. It is actually ``` reduce ``` a less coupled way of writing methods.

``````
// 变形运算
var plusOne = x => x + 1;

// 累积运算
var append = function (newArr, x) {
newArr.push(x);
return newArr;
};

R.transduce(R.map(plusOne), append, [], arr);
// [2, 3, 4, 5]
``````

In the above code, it ``` plusOne ``` is a deformation operation and ``` append ``` an accumulation operation. I used Ramda library ‘s ``` transduce ``` implementation. It can be seen ``` transduce ``` that the deformation and accumulation are ``` reduce ``` separated, and the others are no different.

## Five, the usage of transduce

``` transduce ``` The biggest advantage is that code reuse is easier.

``````
var arr = [1, 2, 3, 4];
var append = function (newArr, x) {
newArr.push(x);
return newArr;
};

// 示例一
var plusOne = x => x + 1;
var square = x => x * x;

R.transduce(
R.map(R.pipe(plusOne, square)),
append,
[],
arr
); // [4, 9, 16, 25]

// 示例二
var isOdd = x => x % 2 === 1;

R.transduce(
R.pipe(R.filter(isOdd), R.map(square)),
append,
[],
arr
); // [1, 9]
``````

In the above code, the first example is the combination of two deformation operations, and the second example is the combination of the filtering operation and the deformation operation. Both of these examples use the Pointfree style .

It can be seen that it ``` transduce ``` is very conducive to code reuse, and a series of simple and reusable functions can be synthesized into complex operations. As an exercise, interested readers can try and use the ``` reduce ``` method to complete the above two examples. You will find that the complexity and number of lines of the code has increased greatly.

## Six, Transformer object

``` transduce ``` The first parameter of the function is an object, called a Transformer object (deformer). In the previous example, ``` R.map(plusOne) ``` what is returned is a Transformer object.

In fact, any object as long as it conforms to the Transformer protocol is a Transformer object.

``````
var Map = function(f, xf) {
return {
"@@transducer/init": function() {
return xf["@@transducer/init"]();
},
"@@transducer/result": function(result) {
return xf["@@transducer/result"](result);
},
"@@transducer/step": function(result, input) {
return xf["@@transducer/step"](result, f(input));
}
};
};
``````

In the above code, the ``` Map ``` function returns a Transformer object. It must have the following three attributes.

• @@transducer/step: Perform transformation operations
• @@transducer/result: return the final value after transformation

All objects conforming to this protocol can be combined with other Transformer objects and serve as ``` transduce ``` the first parameter of the function.

Therefore, ``` transduce ``` the parameter types of the function are as follows.

``````
transduce(
变形器 : Object,
累积器 : Function,
初始值 : Any,
原始数组 : Array
)
``````

## Seven, into method

Finally, you may find that all the previous examples use the same accumulator.

``````
var append = function (newArr, x) {
newArr.push(x);
return newArr;
};
``````

The ``` append ``` function of the above code is a common accumulator. Therefore, the Ramda function library provides a ``` into ``` way to build it. In other words, the ``` into ``` method is equivalent to ``` append ``` the ``` transduce ``` function provided by default .

``````
// 等同于
``````

In the above code, ``` into ``` the first parameter of the method is the initial value, the second parameter is the deformer, and the third parameter is the original array. There is no need to provide an accumulator.

Here is another example.

``````
R.into(
[5, 6],