On a clear day while you’re aggressively sitting around fixing bugs for the maintain project from 2 years ago. Find all disorders up, then you also find the need to fix (ngonroi). Although it is just a piece of code using the find
function of lodash
, it is not normal at all.
1 2 | <span class="token function">find</span> <span class="token punctuation">(</span> item <span class="token operator">=></span> item <span class="token punctuation">.</span> id <span class="token operator">===</span> favoriteId <span class="token punctuation">)</span> <span class="token punctuation">(</span> user <span class="token punctuation">.</span> favorites <span class="token punctuation">)</span> |
The above code of course has been customized so it won’t be revealed =)). The doc of lodash is like this:
1 2 | _ <span class="token punctuation">.</span> <span class="token function">find</span> <span class="token punctuation">(</span> collection <span class="token punctuation">,</span> <span class="token punctuation">[</span> predicate <span class="token operator">=</span> _ <span class="token punctuation">.</span> identity <span class="token punctuation">]</span> <span class="token punctuation">,</span> <span class="token punctuation">[</span> fromIndex <span class="token operator">=</span> <span class="token number">0</span> <span class="token punctuation">]</span> <span class="token punctuation">)</span> |
It looks a little different. Going to ask a brother, the answer came out:
If lodash fp (think) is written normally, it looks like this:
1 2 | <span class="token function">find</span> <span class="token punctuation">(</span> user <span class="token punctuation">.</span> favorites <span class="token punctuation">,</span> item <span class="token operator">=></span> item <span class="token punctuation">.</span> id <span class="token operator">===</span> favoriteId <span class="token punctuation">)</span> |
Lodash writes functional programming, parameter order is the opposite. I’m not used to it yet, I did not even understand what the saga’s generators looked like. Ok man, seems to live. .
Well on top of that is just a narrative for the reason today I wrote this article. It is about functional programming.
Functional programming?
Functional programming (FP) is a programming model – a style of constructing the structure and elements of a computer program – considering computation to evaluate learning functions and avoiding changes to states and data as well. subject to change. – Translate from Wikipedia .
FP is the process of building software using pure functions, avoiding sharing status, data change and side-effects. FP is a declaration, not required, and the application state goes through pure functions. In contrast to object-oriented programming, in which the application state is often shared and associated with methods in objects.
FP is a programming model, meaning it is a way of thinking about building software applications based on the fundamentals mentioned above. To talk about programming model examples, we can talk about object-oriented programming (Object Oriented Programming) or procedural programming (Procedural Programming).
The concept
Pure functions
A basic concept that you can first understand about FP is pure functions.
- It is the function that returns the same result if passed the same parameters.
- It does not cause any side effects.
Suppose that we need a function whose function is to calculate the area of a circle. With an impure function, you will receive the radius as a parameter, and then perform the calculation with the formula radius * radius * PI
.
1 2 3 4 5 6 | <span class="token keyword">const</span> <span class="token constant">PI</span> <span class="token operator">=</span> <span class="token number">3.14</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">calculateArea</span> <span class="token operator">=</span> <span class="token punctuation">(</span> radius <span class="token punctuation">)</span> <span class="token operator">=></span> radius <span class="token operator">*</span> radius <span class="token operator">*</span> <span class="token constant">PI</span> <span class="token punctuation">;</span> <span class="token function">calculateArea</span> <span class="token punctuation">(</span> <span class="token number">10</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// returns 314.0</span> |
In the above function, it uses the global variable PI and does not use it as a parameter to the function. If there is a change in the PI value, the result will be changed. Revise a bit as follows:
1 2 3 4 5 6 | <span class="token keyword">const</span> <span class="token constant">PI</span> <span class="token operator">=</span> <span class="token number">3.14</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">calculateArea</span> <span class="token operator">=</span> <span class="token punctuation">(</span> radius <span class="token punctuation">,</span> pi <span class="token punctuation">)</span> <span class="token operator">=></span> radius <span class="token operator">*</span> radius <span class="token operator">*</span> pi <span class="token punctuation">;</span> <span class="token function">calculateArea</span> <span class="token punctuation">(</span> <span class="token number">10</span> <span class="token punctuation">,</span> <span class="token constant">PI</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// returns 314.0</span> |
Or another example of an impure function is a random number generator.
1 2 3 4 5 6 7 8 | <span class="token keyword">const</span> <span class="token function-variable function">randomText</span> <span class="token operator">=</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> Math <span class="token punctuation">.</span> <span class="token function">random</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">></span> <span class="token number">0.5</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token string">'Yes'</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token string">'No'</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Add an example of the function that passes an integer value as a parameter and returns the result by 1 more unit.
1 2 3 4 5 6 7 8 9 | <span class="token keyword">let</span> counter <span class="token operator">=</span> <span class="token number">1</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">increaseCounter</span> <span class="token operator">=</span> <span class="token punctuation">(</span> value <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> counter <span class="token operator">=</span> value <span class="token operator">+</span> <span class="token number">1</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token function">increaseCounter</span> <span class="token punctuation">(</span> counter <span class="token punctuation">)</span> <span class="token punctuation">;</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> counter <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// 2</span> |
The function above did return a value of 1 unit, but it changed the counter
variable. We try to fix the function to a pure function as follows:
1 2 3 4 5 6 7 | <span class="token keyword">let</span> counter <span class="token operator">=</span> <span class="token number">1</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">increaseCounter</span> <span class="token operator">=</span> <span class="token punctuation">(</span> value <span class="token punctuation">)</span> <span class="token operator">=></span> value <span class="token operator">+</span> <span class="token number">1</span> <span class="token punctuation">;</span> <span class="token function">increaseCounter</span> <span class="token punctuation">(</span> counter <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// 2</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> counter <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// 1</span> |
The result is still increased by 1 unit but the counter
value remains the same, unchanged.
The use of pure function makes it much easier to test. We do not need to mock anything and still be able to perform the test function in a simple way.
Immutability – Immutable
A property that does not change over time or is never changed.
An immutable object is an object that can be modified after it is created. In contrast, a mutable object is any mutable object that is any object that can be modified after it is created. Immutability is a central concept of FP because without it, the data flow in your program will be lost.
Before learning about FP, I still think that const
in JS is the immutability
attribute mentioned here. This seems to be true because the value of const
not changed after creation. However, const
does not create immutable objects. You can still change the properties of the object. Immutable objects are immutable. You can use freeze
to make the value of an object really immutable.
1 2 3 4 5 6 7 8 9 10 | <span class="token keyword">const</span> a <span class="token operator">=</span> Object <span class="token punctuation">.</span> <span class="token function">freeze</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> foo <span class="token punctuation">:</span> <span class="token string">'Hello'</span> <span class="token punctuation">,</span> bar <span class="token punctuation">:</span> <span class="token string">'world'</span> <span class="token punctuation">,</span> baz <span class="token punctuation">:</span> <span class="token string">'!'</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> a <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// { foo: 'Hello', bar: 'world', baz: '!' }</span> a <span class="token punctuation">.</span> foo <span class="token operator">=</span> <span class="token string">'Goodbye'</span> <span class="token punctuation">;</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> a <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// { foo: 'Hello', bar: 'world', baz: '!' }</span> |
You can easily see that the foo
attribute value of object a
not been changed. However, objects created by freeze
are only freeze
on the outside. With the example below, it is changed.
1 2 3 4 5 6 7 8 9 10 | <span class="token keyword">const</span> a <span class="token operator">=</span> Object <span class="token punctuation">.</span> <span class="token function">freeze</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> foo <span class="token punctuation">:</span> <span class="token punctuation">{</span> greeting <span class="token punctuation">:</span> <span class="token string">'Hello'</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> bar <span class="token punctuation">:</span> <span class="token string">'world'</span> <span class="token punctuation">,</span> baz <span class="token punctuation">:</span> <span class="token string">'!'</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> a <span class="token punctuation">.</span> foo <span class="token punctuation">.</span> greeting <span class="token operator">=</span> <span class="token string">'Goodbye'</span> <span class="token punctuation">;</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token template-string"><span class="token string">`</span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> a <span class="token punctuation">.</span> foo <span class="token punctuation">.</span> greeting <span class="token interpolation-punctuation punctuation">}</span></span> <span class="token string">, </span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> a <span class="token punctuation">.</span> bar <span class="token interpolation-punctuation punctuation">}</span></span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> a <span class="token punctuation">.</span> baz <span class="token interpolation-punctuation punctuation">}</span></span> <span class="token string">`</span></span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// Goodbye, world!</span> |
You can see that the parent property has not been changed and for the child properties it is still easy to change even if it uses freeze
.
To solve this problem, many FP programming languages use special invariant data structures. There are several libraries that can be mentioned such as Immutable.js or Mori .
Conclusion
The article seems to be not too long but to write it all down is too long, so it is in the next issues such as:
- Referential transparency
- Functions as first-class entities
- Higher-order functions
I will talk about the next article. Hopefully the article is not too difficult to understand. Thanks for watching .