The concept of High Order Functions in Javascript

Asked

Viewed 4,433 times

12

I’m reading Eloquent Javascript to have a javascript base. I was understanding well, since the fundamental does not change in relation to other languages, such as data types (int, string, bool, Objects, arrays). But I got to the part where Abstraction. I know that this is also part of the other languages, being one of the bases for many Patterns design thereabout,

but I didn’t understand the concept of High Order Functions.

Let’s go to the example shown in Eloquent Javascript p. 90:

Functions that Operate on other functions, either by taking them as Arguments or by returning them, are called Higher-order functions.

(Functions that operate on other functions, whether taking them as arguments or returning them, are called high-order functions).

function greaterThan ( n ) {

  return function ( m ) { return m > n; };

}

var greaterThan10 = greaterThan (10) ;
console . log ( greaterThan10 (11) ) ;

// → true

What I did not understand, mainly, was this example ai. Mainly the part of the arguments.

First he defines greaterThan10 = greaterThan10(10), and passes argument 10 to this Function, and then he can call the variable as Function? What about the arguments? Will the first argument passed in the definition continue there? (10)

I am a little confused, I would like a simpler explanation, or an example where this concept was more visible.

2 answers

17


This concept is very common in functional programming, where the concept is to avoid the state and use functions, function chaining to do what needs to be done by the program. Functions that accept other functions as arguments are called high-order functions.

In general, functions such as .map() and .filter() are functions that fall into this category because they use functions as argument.

Explaining to you your example:

function greaterThan(n) {
    return function(m) {
        return m > n;
    };
}

Here’s a function that returns a function. This is important. The function does not change a state of a variable, it is simply a tool to be chained or a higher order function, ie a tool to create other functions. Hence it is called "abstraction" because it can be used in N different contexts.

You can then generate another, more specific function by doing

var greaterThan10 = greaterThan(10);

which in practice is the same as:

var greaterThan10 = function(m) {
    return m > 10;
};

This function greaterThan10 will return a boolean value. In this case the function takes a number and returns a boolean.

  • 2

    This is what I wasn’t visualizing, the part about var greaterThan10 = function(m) {
 return m > 10;
}; Thank you for helping me understand.

2

I know it’s been years, but I’m going to leave a contribution to that question for people from the future who fall for it...

In addition to what was put by Sergio in the accepted answer, it is worth mentioning the concept of closure, which is fundamental in most implementations of high-order functions.

Closure is the ability of a function to read scopes that are larger than it. For example, access the global state.

This in functional programming is problematic as it makes the function unclean. However, if a high-order function is used to create a controlled (immutable) scope by returning a function that makes use of it, we don’t have this problem.

See the example of the question (I’ll just update the syntax to ES6):

const greaterThan = n => m => m > n;

First we receive n, which is stored. By closure the function m => m > n has access to that n, which cannot be modified.

So when we invoke greaterThan(10) we actually return m => m > 10. After all n is immutable.

If n is immutable the function remains pure (always returns the same value for the same parameters and produces no side effects).

High-order combination with closure is a great tool for specializing generic functions:

const replaceAll = (from, to, text) => text.split(from).joint(to);

In the above function, we have to pass all the parameters at once if we want to make a replaceAll, for example:

replaceAll("{{nome}}", "Jones", "Hello {{nome}}!"); //Hello Jones

If we use closure and high-order, it is possible to use a technique equivalent to partial application (pass fewer parameters than the precise function):

const replaceAll = (from, to) => text => text.split(from).join(to);

Now we can specialize it:

const replaceDotForComma = replaceAll(".", ",");
const replaceDoubleQuoteForSingleQuote = replaceAll("\"", "'");
const replaceWindowsLineBreakForLinux = replaceAll("\r\n", "\n");

To use any of these functions, simply pass the text:

replaceDotForComma("10.5"); // 10,5
replaceDoubleQuoteForSingleQuote('"hello"'); // 'hello'
replaceWindowsLineBreakForLinux("teste/r/n"); // "teste\n"

Not having to pass these parameters every time is useful enough to avoid errors and inconsistencies between the Replaces made in the program...

  • Great answer, congratulations! :)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.