0

I'm trying to write a JavaScript function that lets me do the following: if I call

const multiply = define("x", "y", "x * y");

I want multiply to be

function(x) {
    return function(y) {
        return x * y;
    }
}

The number of arguments is unknown beforehand. The last one is always the final return, every other argument is each a paramenter of an inner function. What should my define function be?

I know I can just write const multiply = x => y => x * y, but I need the code to be as user-friendly as possible and higher-order functions like this are not completely clear to someone who doesn't use them often.

I've tried using the Function constructor but the most I've managed to come up with returns me function(x, y) { return x * y; } which is not what I'm looking for.

My idea is building the function step-by-step, so first I have to create a function f that takes y and returns x * y, then I have to create g that takes x and returns f(y). But this is where I'm stuck.

Can anyone give me a clue on how to solve this problem? Thanks.

1 Answer 1

0

In general, creating code from text at runtime isn't a great idea. But if you trust the source of the text you're creating the functions from, you can use new Function to create a function from text. Just be aware that by its nature, it's allowing arbitrary code execution.

In your case, if the last argument is always the body of the ultimate function and the arguments leading up to it are the parameter names, then a loop should do it:

function define(...args) {
  // Build the text of the functions
  let text = "";
  for (let n = 0; n < args.length; ++n) {
    if (n == args.length - 1) {
      text = text + "(" + args[n] + ")";
    } else {
      text = text + "(" + args[n] + ") => ";
    }
  }
  console.log(text);
  // Create them by creating a wrapper function and executing it.
  // If we wanted to complicate the logic above,
  // we could just use this to create the top-
  // level function and not execute it, but this
  // is simpler.
  return new Function("return " + text + ";")();
}
const multiply = define("x", "y", "x * y");
console.log("multiply(3)(5) => ", multiply(3)(5));
const multiply2 = define("x", "y", "z", "x * y * z");
console.log("multiply2(3)(5)(2) => ", multiply2(3)(5)(2));
.as-console-wrapper {
  max-height: 100% !important;
}

Sign up to request clarification or add additional context in comments.

2 Comments

This works really well and gets the job done. I admit, I really don't like the fact that everything is a string, but that's how the Function constructor work so I guess it's alright. Thank you, I'm marking this as answer.
@MicheleMasina - Well, it has to be a string because that's what the function body you're providing ("x * y") is. It would be possible to use multiple calls to new Function to avoid building up the string, but it would come to the same thing and be more complex, so... :-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.