This is the fifth in the series of how to program functionally in JS! Total seven, seems to have been able to see the other side of victory!!

Gibran once said: We have all been gone so long that we have forgotten why we started.

We already walked too far, down to we had forgotten why embarked.

Therefore, before the fifth chapter, let’s first make a review of the previous chapters:

The above combed

The first paper

“XDM, JS how to function programming? See this is enough!” (a), as “outline”, the key explanation:

  1. This series is an extension of Medium’s “I will Never Understand JS Closures” and “Class” and “Prototype” design Patterns: The Difference between “copy” and “delegate”.

  2. Why do functional programming? All just to make the code more readable!!

  3. Developers prefer explicit I/O to implicit I/o, understand what is explicit and what is implicit!!

  4. A function that accepts or returns one or more functions is called a higher-order function. Closures are the most powerful higher-order functions!!

The second article

“XDM, JS how to function programming? See this is enough! (2)”, talked about two important concepts: partial function, Currie

  1. Function assembly is the most important implementation of functional programming! And the skillful use of partial functions, currying, and their variants is the basis of function assembly.

  2. Partial (sum,1,2)(3)

  3. Sum (1)(2)(3)

The third article

“XDM, JS how to function programming? See this is enough!” (3), came to the “function assembly” this point:

  1. Again, function assembly is the most important implementation of functional programming!!

  2. Function assembly conforms to “declarative programming style”, that is, you know “what” it is when you declare it! Without knowing exactly what it “did” (imperative function style)!

  3. For example, when you see the assembled function call, compose(skipShortWords, unique, words)(text), you know that it is used to change text into words, then unique, and then filter shorter words. Very clear!

  4. compose(..) Function and partial (..) Function combination, you can achieve a rich and colorful assembly form!

  5. Encapsulating abstract functions is a skill! Not enough, not too much!

Article 4

“XDM, JS how to function programming? See this is enough!”

  1. Developers prefer explicit I/O to implicit I/O. Learn functional programming.

  2. Some of the ways to deal with side effects are: define constants, specify I/O, specify dependencies, and use idempotences. Watch out for idempotences!

  3. We like functions without side effects, i.e., pure functions!!

  4. If a tree falls in a forest and no one is around to hear it, does it make a sound? If you encapsulate a high level function, will the outside world know about it even if it has side effects inside? Is it still a pure function?

That’s our brief review!

We may need more time to practice and experience:

  1. Partial functionpartial(..)And function assemblycompose(..)Variant and application;
  2. The ability to abstract;
  3. Encapsulate high-level pure functions;

OK! Review the old and learn the new.

In Part five, we will share the most common phenomenon, array manipulation, based on practice, and see how it embodies the spirit of functional programming!

Array of three musketeers

The three musketeers are: Map (..) And the filter (..) And reduce (..) .

map

We all use ES6 map(..) We know very well what it is.

Easily write a map(..) The use of:

[1,2,3].map(item => item + 1)
Copy the code

However, the map (..) “What does it do”, that is, how it is on the inside, you know?

We can implement a function map(..) natively :

function map(mapperFn,arr) { var newList = []; for (let idx = 0; idx < arr.length; idx++) { newList.push( mapperFn( arr[idx], idx, arr ) ); } return newList; } the map (item = > item + 1, [1, 2, 3])Copy the code

We put a mapperFn(..) Encapsulate the simulated Map (..) Function, which is also traversed internally by a for loop.

We can also use map(..) Do more:

For example, we first put functions in a list, then combine each function in the list, and finally execute them, like this:

var increment = v => ++v; var decrement = v => --v; var square = v => v * v; var double = v => v * 2; [increment,decrement,square] .map( fn => compose( fn, double ) ) .map( fn => fn( 3 ) ); / /,5,36 [7]Copy the code

A fine taste ~

filter

If the map (..) Is the essence of mapping values, filter(..) Is the essence of filtering values. As shown in the figure:

[1, 2, 3]. The filter (item = > item > 2)Copy the code

Hand write a filter(..) Function:

function filter(predicateFn,arr) { var newList = []; for (let idx = 0; idx < arr.length; idx++) { if (predicateFn( arr[idx], idx, arr )) { newList.push( arr[idx] ); } } return newList; } filter (item = > item > 2, [1, 2, 3])Copy the code

Again, we take a function as an argument, process the same arR passed in, and iterate through the filter to get the target array.

reduce

map(..) And the filter (..) Generates a new array, and the third operation (reduce(..)) ) typically merges (or reduces) the values in a list to a single value (not a list).

,10,15 [5]. The reduce ((product, v) = > product * v, 3);Copy the code

Process:

  1. 3 times 5 is 15
  2. 15 times 10 is 150
  3. 150 times 15 is 2250

Manually implementing the reduce function is a little more complicated than the first two:

function reduce(reducerFn,initialValue,arr) {
    var acc, startIdx;

    if (arguments.length == 3) {
        acc = initialValue;
        startIdx = 0;
    }
    else if (arr.length > 0) {
        acc = arr[0];
        startIdx = 1;
    }
    else {
        throw new Error( "Must provide at least one value." );
    }

    for (let idx = startIdx; idx < arr.length; idx++) {
        acc = reducerFn( acc, arr[idx], idx, arr );
    }

    return acc;
}
Copy the code

Unlike the map (..) And the filter (..) There is no requirement for the order in which the array is passed. reduce(..) Make it clear that you want to go left to right.

Advanced operation

Based on the map (..) And the filter (..) And reduce (..) Let’s look at some more complicated operations;

duplicate removal

Implementation:

var unique =
    arr =>
        arr.filter(
            (v,idx) =>
                arr.indexOf( v ) == idx
        );

unique( [1,4,7,1,3,1,7,9,2,6,4,0,5,3] );        
Copy the code

The idea is that when filtering elements from left to right, the idX position of a list item and indexOf(..) When the positions are found equal, the list item appears for the first time, in which case the list item is added to the new array.

Of course, there are many ways to do this, but the advantage of these is that they use built-in list operations, and they can be more easily chained/combined with other list operations.

Let me write reduce(..) Implementation:

var unique =
    arr =>
        arr.reduce(
            (list,v) =>
                list.indexOf( v ) == -1 ?
                    ( list.push( v ), list ) : list
        , [] );
Copy the code

Dimension reduction

Convert a two-dimensional array to a one-dimensional array

[[1, 2, 3], 4, 5, [6, [7, 8]]] = > [1, 2, 3, 4, 5, 6, 7, 8]Copy the code

Implementation:

var flatten =
    arr =>
        arr.reduce(
            (list,v) =>
                list.concat( Array.isArray( v ) ? flatten( v ) : v )
        , [] );
Copy the code

You can also add a parameter depth to specify the number of levels to reduce the dimension:

var flatten = (arr,depth = Infinity) => arr.reduce( (list,v) => list.concat( depth > 0 ? (depth > 1 && Array.isArray( v ) ? flatten( v, depth - 1 ) : v ) : [v] ) , [] ); Flatten ([[0, 1], 2, 3, [4, [5, 6], [8, [9, [10, 11, 12] [13]]]]], 2); / / [0,1,2,3,4,5,6,7,8, [9, 10, 11, 12] [13]]]Copy the code

Now, if that’s complicated, you can just call it as a library. In fact, we’ll talk more about functional programming libraries later on!

merge

Take a closer look at the following three pieces of code. Which one do you find easier to understand? Which paragraph is more consistent with functional programming?

// Implement 1 [1,2,3,4,5].filter(isOdd).map(double).reduce(sum, 0); // 18 // realize 2 reduce(map(filter([1,2,3,4,5], isOdd), double), sum, 0); Compose (partialRight(reduce, sum, 0), partialRight(map, double), partialRight(filter, IsOdd)) ([1,2,3,4,5]); / / 18Copy the code

Can’t decide between segments 1 and 3?

Here’s another example:

var removeInvalidChars = str => str.replace( /[^\w]*/g, "" ); var upper = str => str.toUpperCase(); var elide = str => str.length > 10 ? str.substr( 0, 7 ) + "..." : str; var words = "Mr. Jones isn't responsible for this disaster!" .split( /\s/ ); words; // ["Mr.","Jones","isn't","responsible","for","this","disaster!"] // Words.map (removeInvalidChars).map(upper).map(elide); / / / "MR", "JONES", "ISNT", "RESPONS...", "FOR" and "THIS", "the emergence of"] / / section 3 words. The map (compose (elide, upper, removeInvalidChars ) ); // ["MR","JONES","ISNT","RESPONS...","FOR","THIS","DISASTER"]Copy the code

Here’s the point:

We can take the three separate adjacent maps (..) The call step is viewed as a combination of transformations. Because they are unary functions, and each return value is the next point input value. We can use compose(..) Perform the mapping function and pass this combination function to a single map(..) In the call:

So: Segment 3, this fusion technique, is a common way to optimize performance.

Stage summary

Above, we see:

Three powerful, universal list operations:

  1. map(..) : Converts the value of a list item to a new list
  2. filter(..) : Selects or filters the values of list items into a new array
  3. reduce(..) : Merges the values in the list and produces an additional value (possibly a non-list value);

These are the array traversals we usually use the most, but this time we’ve taken them up a notch with the help of functional programming ideas!

These advanced operations: Unique (..) , flatten (..) (in fact, there are many other advanced operations), it is worth us to study, feel and experience, finally applied to practice!!

OK~ that’s all for this time, look forward to seeing you next time ~

I am Nuggets Anthony, the public number [nuggets Anthony], input exposure input, technical insights into life!