Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript compose functions

I am reading a book which contains the following example:

var composition1 = function(f, g) {
  return function(x) {
    return f(g(x));
  }
};

Then the author writes: "...naive implementation of composition, because it does not take the execution context into account..."

So the preferred function is that one:

var composition2 = function(f, g) {
  return function() {
    return f.call(this, g.apply(this, arguments));
  }
}; 

Followed by an entire example:

var composition2 = function composition2(f, g) {
    return function() {
        return f.call(this, g.apply(this, arguments));
    }
};

var addFour = function addFour(x) {
    return x + 4;
};

var timesSeven = function timesSeven(x) {
    return x * 7;
};

var addFourtimesSeven2 = composition2(timesSeven, addFour);
var result2 = addFourtimesSeven2(2);
console.log(result2);

Could someone please explain to me why the composition2 function is the preferred one (maybe with an example)?

EDIT:

In the meantime i have tried to use methods as arguments as suggested, but it did not work. The result was NaN:

var composition1 = function composition1(f, g) {
    return function(x) {
        return f(g(x));
    };
};

var composition2 = function composition2(f, g) {
    return function() {
        return f.call(this, g.apply(this, arguments));
    }
};

var addFour = {
    myMethod: function addFour(x) {
        return x + this.number;
    },
    number: 4
};

var timesSeven = {
    myMethod: function timesSeven(x) {
        return x * this.number;
    },
    number: 7
};

var addFourtimesSeven1 = composition1(timesSeven.myMethod, addFour.myMethod);
var result1 = addFourtimesSeven1(2);
console.log(result1);

var addFourtimesSeven2 = composition2(timesSeven.myMethod, addFour.myMethod);
var result2 = addFourtimesSeven2(2);
console.log(result2);
like image 772
JShinigami Avatar asked Apr 16 '16 09:04

JShinigami


People also ask

How do you compose functions?

In mathematics, function composition is an operation ∘ that takes two functions f and g, and produces a function h = g ∘ f such that h(x) = g(f(x)). In this operation, the function g is applied to the result of applying the function f to x.

What is the point of composing functions?

Composition of functions is the process of plugging one function into another, and simplifying or evaluating the result at a given x-value. Suppose you are given the two functions f(x) = 2x + 3 and g(x) = −x2 + 5. Composition means that you can plug g(x) into f(x), (or vice versa).

What does it mean to compose functions together?

"Function Composition" is applying one function to the results of another: The result of f() is sent through g() It is written: (g º f)(x)

How do you create a function in JavaScript?

A JavaScript function is defined with the function keyword, followed by a name, followed by parentheses (). Function names can contain letters, digits, underscores, and dollar signs (same rules as variables). The parentheses may include parameter names separated by commas: (parameter1, parameter2, ...)


1 Answers

This just answers what composition2 actually does:

composition2 is used when you want to keep this as context in the functions itself. The following example shows that the result is 60 by using data.a and data.b:

'use strict';

var multiply = function(value) {
    return value * this.a;
}
var add = function(value) {
    return value + this.b;
}

var data = {
    a: 10,
    b: 4,
    func: composition2(multiply, add)
};

var result = data.func(2);
// uses 'data' as 'this' inside the 'add' and 'multiply' functions
// (2 + 4) * 10 = 60

But yet, it still breaks the following example (unfortunately):

'use strict';

function Foo() {
    this.a = 10;
    this.b = 4;
}
Foo.prototype.multiply = function(value) {
    return value * this.a;
};
Foo.prototype.add = function(value) {
    return value + this.b;
};


var foo = new Foo();

var func = composition2(foo.multiply, foo.add);
var result = func(2); // Uncaught TypeError: Cannot read property 'b' of undefined

Because the context of composition2 (this) is undefined (and is not called in any other way, such as .apply, .call or obj.func()), you'd end up with this being undefined in the functions as well.

On the other hand, we can give it another context by using the following code:

'use strict';
var foo = new Foo();

var data = {
    a: 20,
    b: 8,
    func: composition2(foo.multiply, foo.add)
}

var result = data.func(2); 
// uses 'data' as 'this'
// (2 + 8) * 10 = 200 :)

Or by explicitly setting the context:

'use strict';

var multiply = function(value) {
    return value * this.a;
};
var add = function(value) {
    return value + this.b;
};


var a = 20;
var b = 8;

var func = composition2(multiply, add);

// All the same
var result1 = this.func(2);
var result2 = func.call(this, 2);
var result3 = func.apply(this, [2]);
like image 89
Caramiriel Avatar answered Nov 06 '22 17:11

Caramiriel