Search code examples
javascriptcallbackarrow-functions

Return and pass a callback in arrow function format


I wanna

  1. return an arrow function and
  2. pass an arrow function to another function.

Code:

const NumberValue = {
  GREATER_THAN_0: i => i > 0,
  LESS_THAN_0: i => i < 0,
  EQUAL_TO_0: i => i == 0
};

function printStatistics(...a) {
    for (var key in NumberValue) {
        if (NumberValue.hasOwnProperty(key)) {
          console.log(key + " -> " + sum(NumberValue[key],a));
        }
    }
}

function sum(callback, ...a) {
    return a.filter(callback);
}

console.log(printStatistics(-5, 5, 4, 3, 2, 1, 0, -1));

I'm trying the following: I pass to printStatistics(...a) an int array then I wanna print each key of the NumberValue object with an array of int that must to be filtered according to each arrow expression that are stored in the respective values of the NumberValue object.

I don't know what is not working. Whether the return of the arrow functions or to pass they to another function.

Expected results:

GREATER_THAN_0 -> [5,4,3,2,1] LESS_THAN_0 -> [-5,-1] EQUAL_TO_0 -> [0]

But I am getting:

GREATER_THAN_0 ->
LESS_THAN_0 ->
EQUAL_TO_0 ->
undefined

In resume

So how can I return and pass an arrow function correctly?


Solution

  • Problem

    The problem is that you use ...a twice. This is rest parameters syntax and it turns all the parameters into an array. However, since it's used two times, the first one converts the parameters to an array, the second time you just pass said array and it's wrapped into another array:

    console.log("result:", foo(1, 2, 3));
    
    function foo(...a) { 
      console.log("`a` in foo:", a); // a = [1, 2, 3]
      return bar(a);
    }
    
    function bar(...a) {
      console.log("`a` in bar:", a); // a = [[1, 2, 3]] - array inside array
      return a;
    }

    Solution

    There are two ways to solve this:

    Don't use rest parameters

    You can simply remove the rest parameter syntax from the second call and this will avoid wrapping the array into another array

    console.log("result:", foo(1, 2, 3));
    
    function foo(...a) { 
      console.log("`a` in foo:", a); // a = [1, 2, 3]
      return bar(a);
    }
    
    function bar(a) { //no rest parameter syntax
      console.log("`a` in bar:", a); // a = [1, 2, 3] - single array
      return a;
    }

    const NumberValue = {
      GREATER_THAN_0: i => i > 0,
      LESS_THAN_0: i => i < 0,
      EQUAL_TO_0: i => i == 0
    };
    
    function printStatistics(...a) {
        for (var key in NumberValue) {
            if (NumberValue.hasOwnProperty(key)) {
              console.log(key + " -> " + sum(NumberValue[key],a));
            }
        }
    }
    
    function sum(callback, a) {
        return a.filter(callback);
    }
    
    console.log(printStatistics(-5, 5, 4, 3, 2, 1, 0, -1));

    Spread the array into the call

    If you want to still be able to call the second function with variable amount of arguments, you can leave the rest parameter syntax but instead use spread syntax to make the array into a list of arguments:

    console.log("result:", foo(1, 2, 3));
    
    function foo(...a) { 
      console.log("`a` in foo:", a); // a = [1, 2, 3]
      return bar(a);
    }
    
    function bar(...a) {
      console.log("`a` in bar:", a); // a = [[1, 2, 3]] - array inside array
      return a;
    }

    console.log("result:", foo(1, 2, 3));
    
    function foo(...a) { 
      console.log("`a` in foo:", a); // a = [1, 2, 3]
      return bar(...a); //spread syntax
    }
    
    function bar(...a) { //rest syntax
      console.log("`a` in bar:", a); // a = [1, 2, 3] - single array
      return a;
    }

    const NumberValue = {
      GREATER_THAN_0: i => i > 0,
      LESS_THAN_0: i => i < 0,
      EQUAL_TO_0: i => i == 0
    };
    
    function printStatistics(...a) {
        for (var key in NumberValue) {
            if (NumberValue.hasOwnProperty(key)) {
              console.log(key + " -> " + sum(NumberValue[key], ...a));
            }
        }
    }
    
    function sum(callback, ...a) {
        return a.filter(callback);
    }
    
    console.log(printStatistics(-5, 5, 4, 3, 2, 1, 0, -1));