Function corrilization -- six pulse sword

Keywords: Javascript Programming less

Are you in? It should be. by the way, there's no six pulse sword here, or even it can't compete with the six pulse sword. But the title of this blog post is called this. It's not changed. What's more?

Back to the main topic, the functions in javascript are curried, and many articles on the Internet are written in various ways, even with fancy skills. (it's rarely used in practical work) the author looked at some of them. I thought I knew about it, but it became more and more confused. So I spent some time to sort them out, hoping to help you.

Authoritative sources

function currying, which is used to create a function with one or more parameters set. The basic method of function currification is the same as function binding: use a closure to return a function. The difference between the two is that when a function is called, the returned function also needs to set some incoming parameters.

function add(num1, num2){ 
 return num1 + num2; 
} 
function curriedAdd(num2){ 
 return add(5, num2); 
} 
alert(add(2, 3)); //5 
alert(curriedAdd(3)); //8

This code defines two functions: add() and curiedadd(). The latter is essentially the add () version with the first parameter of 5 in any case. Although curiedadd () is not technically a curried function, it shows its concept well.

The curly function is usually created dynamically by calling another function and passing in the function to be curly and the necessary parameters for it. The following is a general way to create curried functions.

function curry(fn){
  var args=Array.prototype.slice.call(arguments, 1);
  return function(){
    var innerArgs=Array.prototype.slice.call(arguments);
    var finalArgs=args.concat(innerArgs);
    return fn.apply(null, finalArgs);
  };
}

The above content comes from "javascript advanced programming" Redbook.

Note that the bold part curiedadd() is not a currifying function

Expanding A

Source one
For an interview question, please implement a Coriolis function
Then the original blog posted such a code

const curry = (fn, ...args1) => (...args2) => (
 arg => arg.length === fn.length ? fn(...arg) : curry(fn, ...arg)
)([...args1, ...args2]);

// call
const foo = (a, b, c) => a * b * c;
curry(foo)(2, 3, 4); // -> 24
curry(foo, 2)(3, 4); // -> 24
curry(foo, 2, 3)(4); // -> 24
curry(foo, 2, 3, 4)(); // -> 24

Seeing the above code, I have to use the "horizontal groove" arrow function to simplify the function writing. I am a bit confused by the continuous three arrows above. Who passed the parameters in brackets at last? Make it look better

const curry = function(fn, ...args1){
    
    return function (...args2) {
        
        return function(arg){
            return arg.length === fn.length ? fn(...arg) : curry(fn, ...arg)
        }([...args1, ...args2]);
     
    }
}

The general-purpose korilization function is just the return function in the function. This is the return function in the function. The function in the function returns another function. The most internal function is called directly in the intermediate function.
The principle of this universal curry function is similar to the recursive call, which judges the number of parameters. If the original function fn has 8 parameters, it will continue to call itself recursively as long as it passes less than 8 parameters. If it does, it will call the original function fn

Expanding B

Source two
An add method is implemented to make the calculation result meet the following expectations:
add(1)(2)(3) = 6;
add(1, 2, 3)(4) = 10;
add(1)(2)(3)(4)(5) = 15;

function add() {
    // At first execution, an array is defined to store all parameters
    var _args = Array.prototype.slice.call(arguments);

    // Declare a function internally, save ﹐ args and collect all parameter values with the characteristics of closure
    var _adder = function() {
    _args.push(...arguments);
    return _adder;
    };

    // Using the property of toString implicit conversion, when the last execution, implicit conversion is performed, and the final value return is calculated
    _adder.toString = function () {
        return _args.reduce(function (a, b) {
            return a + b;
        });
    }
    return _adder;
}

The above content code is completely quoted from "source 2". Here is my personal experiment:

It's a bit interesting, but when we call it in the following way, it really works

console.log("add(1)(2)(3):",add(1)(2)(3));
console.assert(add(2, 6)(1)!=9, "add(2, 6)(1)!=9");
console.log(add(1, 2, 3)(4)=="10")
console.log(add(1, 2, 3)(4)==10)
console.log(add(1, 2, 3)(4)==="10")

The output result is:
add(1)(2)(3): 6
Assertion failed: add(2, 6)(1)!=9
true
true
false

It seems not too strict. add is obviously a function. If it is called, what it returns is actually an internal function. However, this internal function rewrites toString to get the expected value at some default transformations. Corresponding to it is valueOf

Add the following code to the original add function

_adder.valueOf = function () {
  return 0;
}

So, what do you think is the output of the following code?

console.log(add(1, 2, 3)(4)) 
console.log("hello boy:",add(1, 2, 3)(4)) 
console.log(add(1, 2, 3)(4)=="10") 
console.log(add(1, 2, 3)(4)==10)

... thinking

The results of the four lines are as follows:
{ [Function: _adder] toString: [Function], valueOf: [Function] }
hello boy: 10
false
false

----Is there a surprise?

therefore

Is there any harvest

Posted by Sulman on Sat, 07 Dec 2019 16:36:41 -0800