Preface
Function Currying is a technical way to simplify multiple parameters into single parameters. It ultimately supports continuous calls of methods, returning a new function every time, and terminating the function call when the conditions are finally met or all parameters are used.
Scene Example
Unlike other articles, I will focus on sharing some classic usage scenarios of Curry in this article, so that you can effectively improve the maintainability of your code after learning this technique.
Write reusable small module code
For example, we have a method part that has the same logic prefix, and the subsequent execution results are different due to different parameters. The following is the code part.
To calculate the discount of a product, we need to return the actual price based on different discounts and the entry parameters of the product.
// before function getPrice(price,discount){ return price * discount; } let price = getPrice(500,0.1); // after function getPrice(discount){ return price =>{ return price * discount } } // Use, under this use effect, we can fixedly dismember the function with a 10% discount,//That is, the price of products using 0.1 discount can be simplified to transmit this discount, thereby achieving the purpose of simplifying parameters.//Then in terms of function operation, it is more efficient than before. If the process of analyzing discounts is more complicated,let tenDiscount = getPrice(0.1); let price = tenDiscount(500); let price = getPrice(0.1)(500)
It looks a bit useless because our original writing is very simple, and using currying makes simple things complicated. This is mainly because we have not achieved the classic scenario where we want to turn a function into currying. If the code below becomes like this, maybe you can realize that it will be very convenient if Curry is used, because several processing has been done for the first parameter, which can even be called an algorithm or a complete logical judgment process. Then if multiple parameter calls involve the call of this method, this part of the logic of the same parameter can be skipped in common. Codepen connection:Link
// complexed fun function getPriceComplex(price,discount){ let actualDiscount = 1; if(discount > 0.8 ) { actualDiscount = 0.8; } else if(discount > 0.5){ actualDiscount = 0.5; } else { actualDiscount = 0.1; } let actualPrice = price - price % 100 ; return actualPrice * actualDiscount; } // complexed fun better function getPriceComplexBetter(discount){ let actualDiscount = 1; if(discount > 0.8 ) { actualDiscount = 0.8; } else if(discount > 0.5){ actualDiscount = 0.5; } else { actualDiscount = 0.1; } return price => { let actualPrice = price - price % 100 ; return actualPrice * actualDiscount; } } (getPriceComplex(500,0.9)) let exp1 = getPriceComplexCp(0.9); (exp1); /** price => { let actualPrice = price - price % 100; return actualPrice * actualDiscount; }*/ // With the same input parameters, the execution results of the previous code logic can be cached. The module can be reused, if your previous logic is a pure function(exp1(500))// 400 (exp1(400))// 320 // get real discount // When your logic for the first parameter is more complicated, this is recommended for the maintenance perspective;// When your other logic is also based on this return result, it is recommended to do so from the perspective of reuse.function getActualDiscount(discount){ let actualDiscount = 1; if(discount > 0.8 ) { actualDiscount = 0.8; } else if(discount > 0.5){ actualDiscount = 0.5; } else { actualDiscount = 0.1; } return actualDiscount; } // complexed fun best function getPriceComplexBest(discount){ let actualDiscount =getActualDiscount(discount); return price => { let actualPrice = price - price % 100 ; return actualPrice * actualDiscount; } }
In summary, no matter what, we use some skills, encapsulation or other to make the code more usable. The originally complex, untested and incomprehensible code becomes more conditioned and more performance-saving. When this is the case in your way of thinking, you will not feel that it is used for the sake of form, but that is your coding habits or style.
Simple transformation of ordinary functions to Keli
If we need to quickly transform a function that is not Curry, and without affecting the original main code logic, how can we write our code?
// Only two parameters are consideredfunction add(a,b){ return a + b } // But if you use Currying method: when two parameters, this will change very much to the original code, and for some complex logic, it is basically impossiblefunction curryAdd(...args){ return (...newArgs) => { return anoNumber * number; }; } // We write a general curry function method. After the conversion of this function, we can simplify the call methodfunction curry = (fn,...args){ return (..._args)=>{ return fn(...args, ..._arg); } } let curryAdd = curry(add,10); let curryAdd2 = curryAdd(11)
Accumulation of uncertain parameters
A more classic practice problem, use the following code to implement the currying method. The difficulty is as follows: If you have not understood currying, you may feel that it is basically impossible to complete.
1 Dynamically enter the number of parameters, which may also be completed through arguments loop 2. New parameters can be accepted and accumulated. This must be a new function with the previous result. It is required to have currying characteristics. 3. Every time the parameters are not appended, the value you can get is required. This requires you to understand the toString method to change the result value.
Implement an add method so that the calculation results can meet the following expectations: add(1)(2)(3) = 6
add(1, 2, 3)(4) = 10
add(1)(2)(3)(4)(5) = 15
function add() { // During the first execution, define an array specifically used to store all parameters var _args = [].(arguments); // Declare a function internally, use the closure's characteristics to save _args and collect all parameter values. All parameters have been collected as arrays during execution. var adder = function () { var _adder = function() { // Perform the collection action, and each incoming parameter is accumulated to the original parameter [].(_args, [].(arguments)); return _adder; }; //Use the implicit conversion feature, implicit conversion when the final execution is finally executed, and calculate the final value to return _adder.toString = function () { return _args.reduce(function (a, b) { return a + b; }); } return _adder; } return adder(_args); }
Note: The method in codepen is rewritten and there will be an error problem. You can debug this method directly through the browser's console.
Some parameters are applied
Some parameter applications refer to some scenarios that want to pass multiple parameters in a fixed way to obtain a fixed function, and then execute the code based on this function. Similar to a discount parameter in the first example, the use of the discount algorithm is derived. Let's complicate the first example a little more. It will become like this.
function getActualDiscount(custoemrLevel,discount){ } function getPriceComplex (custoemrLevel,discount){ let actualDiscount = getActualDiscount(custoemrLevel,discount); return price=>{ return price * actualDiscount; } } // Level 1 discount strategylet strategyLev1WithOnepoint = getPriceComplex('lev1',0.1) ; let actualPrice = strategyLev1WithOnepoint(500);
The above is the detailed explanation and integration of the scenarios to understand the function Curry (Introduction) introduced by the editor. I hope it will be helpful to everyone. If you have any questions, please leave me a message and the editor will reply to everyone in time. Thank you very much for your support for my website!