Here are two examples from which you understand what composition is from real life.
First Example: Discount
Let's say, you want to buy a 30-dollar shirt, and it is on sale at 50% off. It means that price of shirt is 15 dollar. Now, you must calculate what the shirt will cost after sales tax (let's say it is 10%). Your total cost for the shirt after the discount and sales tax will be $16.5. This process of computation can be expressed as a composite function.
Here, the raw thing is price of item and we are performing a series of operation to get the final price.
Second Example: Blow glass forming
In the formation of the glass, the mould has to go through a lot of processes to finally be converted into a bottle. This series of processes can be thought of as composition.
You can see from the above explanation that there are a series of operations that are performed on raw material or the initial price of the item and its subsequently changed form. All these examples are composition example.
Composition in programming:
Similarly, in programming, we have to perform a series of operations on the raw data to get useful data. If we combine or treat these series of operations together, then it is called composition.
In composition, the outcome of a function is input to the another function.
How to implement composition?
As we know that output of a function is input to another function. Adding these functions together in such a way that the output of a function is input to another function is called composition.
const add2 = (num) => num + 2;const multiplyBy3 = num => num * 3;const reduceBy2 = num => num - 2;const divideBy2 = num => num / 2;const num = 16;const result = add2(multiplyBy3(reduceBy2(divideBy2(num))));console.log(result);
Generic ways to implement composition:
In coding, we can do composition in two ways if we have a list of functions in an array. We can apply functions from front to back or back to front.
const listofFunctions = [func1, func2, func3];
First approach would be applying functions on value from left to right. There is another name for it → join
.
The second approach is applying functions on the value from right to left. There is another name for it → compose
.
Implementing the join method
In the arrayOfFuns
, you can have as many functions as you want.
const sumBy2 = (item) => item + 2;const multiplyBy2 = (item) => item * 2;const arrayOfFuns = [sumBy2, multiplyBy2];const join = ([...arrayOfFuns]) => (value) => {return arrayOfFuns.reduce((acc, fn) => fn(acc), value);};const joinedFns = join(arrayOfFuns);const value = 5;const result = joinedFns(value);console.log(result); // 14
As you can see in the above implementation, the application of the functions the value is being done from left to right as reduce
method do so from left to right.
Implementing the compose method
Here, in the arrayOfFuns
, you can have as many functions as you want.
const sumBy2 = (item) => item + 2;const multiplyBy2 = (item) => item * 2;const arrayOfFuns = [sumBy2, multiplyBy2];const compose = ([...arrayOfFuns]) => (value) => {return arrayOfFuns.reduceRight((acc, fn) => fn(acc), value);};const composedFns = compose(arrayOfFuns);const value = 5;const result = composedFns(value);console.log(result); // 12
In this implementation, the application of the functions on the value is being done from right to left because of the reduceRight
method.
Practical use of composition:
The composition is very useful in authentication and sharing context objects across the application etc.
Where had you used composition?
Thanks for reading this article. Keep coding and keep solving problems.