js function repeatedly invokes through an array of multipliers

121 views Asked by At

I am running into an error: Uncaught TypeError TypeError: multipliers.reduce(...) is not a function. I was looking at currying and partial application. I expected multiply function to correctly invoke through an array of multipliers. Can someone please explain what I'm missing in my multiply function?

multiply function that multiplies integers, but in a special way. The function's output can be invoked repeatedly until you call it with no arguments. For example, multiply(3)(4)(5)() should return 3 * 4 * 5 = 60. I am using a helper function solution(multipliers) that takes all the multipliers and then passes them to multiply as described above.

Input

multipliers: [3, 4, 5]

Output

60

Code

function multiply(x) {
    return function(y) { // anonymous function
        return function(z) { // anonymous function
            return x * y * z;
        }
    }
}

// this function lets you invoke something like multiply(3)(4)(5)() with dynamic arguments
function solution(multipliers) {
    return (multipliers.reduce((prev, arg) => {
        if (prev) {
            return prev(arg);
        }
        return multiply(arg);
    }, null))();
}

console.log(solution([3, 4, 5]));
5

There are 5 answers

0
imparante On BEST ANSWER

I was able to modify only the multiply function using currying thanks to @ghassen-louhaichi's link to a related question: Create a function with an undetermined number of successive calls.

function multiply(x) {
    return function() {
        if (arguments.length == 0) {
            return x;
        } else {
            return multiply(x * arguments[0]);
        }
    }
}

// this function lets you invoke something like multiply(3)(4)(5)() with dynamic arguments
function solution(multipliers) {
    return (multipliers.reduce((prev, arg) => {
        if (prev) {
            return prev(arg);
        }
        return multiply(arg);
    }, null))();
}

console.log(solution([3, 4, 5]));

The first call to multiply, returns the inner function. depending on the number of arguments passed to the inner function, it returns the value of multiply's argument as it is or it calls again ´multiply´ with the updated running total (thus returning again the inner function to be called again).

The limitation (of this implementation) is that you HAVE TO make a final call with no arguments to have to final value.

2
Sharan Balakrishnan On

You have to push all parameters to an array before calling an array method on it. Or else you can use the arguments parameters inside the function to get all the parameters.

Can you share how the function has been called?

2
Bergi On

Use the multiply function as the initial value for the reduce call, and drop the final ():

function solution(multipliers) {
    return multipliers.reduce((prev, arg) => prev(arg), multiply);
}
console.log(solution([3, 4, 5]));

function multiply(x) {
    return function(y) {
        return function(z) {
            return x * y + z;
        }
    }
}

1
Aadit M Shah On

Your multiply function is defined incorrectly. If you want multiply(3)(4)(5)() to evaluate to 60 then you need to define the multiply function as follows.

// x is required, y is optional, both are numbers
const getMultiply = (x) => (y) =>
  typeof y === "undefined" ? x : getMultiply(x * y);

// 1 is the identity element of multiplication
const multiply = getMultiply(1);

console.log(multiply(3)(4)(5)()); // 60

Once you define multiply correctly, you can define solution as follows.

// x is required, y is optional, both are numbers
const getMultiply = (x) => (y) =>
  typeof y === "undefined" ? x : getMultiply(x * y);

// 1 is the identity element of multiplication
const multiply = getMultiply(1);

const solution = (multipliers) =>
  multipliers.reduce((f, x) => f(x), multiply)();

console.log(solution([3, 4, 5])); // 60

0
M0nst3R On

You are invoking the call to multipliers.reduce(...) as an IIFE. This won't work because the result of calling the reduce in your code is not a function, it's instead a number.

In the code you provided, you essentially wrote:

function solution(multipliers) {
  return (60)(); // 60 here being the result of calling the reduce
}

Which explains the error you received.

All you need to do is omit the IIFE call. Your function becomes:

function solution(multipliers) {
    return multipliers.reduce((prev, arg) => {
        if (prev) {
            return prev(arg);
        }
        return multiply(arg);
    }, null);
}

Finally, I suggest looking at some of the other answers here or in this question for a better implementation of your multiply function to make it more generic.