Function to cache its argument's return value

You should only assign num = func(x) when num is undefined - that is, on the very first call of retFunc:

function once(func) {
  let num; 
  function retFunc(x){
    if (num === undefined) {
      num = func(x);
    }
    return num;
  }
  return retFunc;
}

function addByTwo(input){
  return input + 2;
}

var onceFunc = once(addByTwo);

console.log(onceFunc(4));  //should log 6
console.log(onceFunc(10));  //should log 6
console.log(onceFunc(9001));  //should log 6

But this isn't a guaranteed general solution - what if the passed function (addByTwo in your example) results in undefined when called? Then, the === undefined check won't work. So, it might be better to set a flag or something similar, and reassign that flag the first time the callback is called:

function once(func) {
  let num;
  let done = false;
  function retFunc(x){
    if (!done) {
      done = true;
      num = func(x);
    }
    return num;
  }
  return retFunc;
}

function returnsUndefinedOn1(input){
  return input === 1 ? undefined : input;
}

var onceFunc = once(returnsUndefinedOn1);

console.log(onceFunc(1));
console.log(onceFunc(10));
console.log(onceFunc(9001));


You should only call the function and assign num if it's undefined, otherwise you overwrite it every time:

function once(func) {
  let num;

  function retFunc(x) {
    num = (num === undefined) ? func(x) : num
    return num;
  }
  return retFunc;
}

function addByTwo(input) {
  return input + 2;
}

var onceFunc = once(addByTwo);

console.log(onceFunc(4)); //should log 6
console.log(onceFunc(10)); //should log 6
console.log(onceFunc(9001)); //should log 6

Note that if the function you pass in returns undefined it will be called more than once. If you need to handle that case you can set a flag to indicate whether the cached value is valid.


What you're missing is removing the original function after the first execution. You should modify your code in the following way:

function once(func) {
  let num; 
  function retFunc(x){
      if (func)
          num = func(x);
      func = null;
      return num;
 }
    return retFunc;
}

function addByTwo(input){
  return input + 2;
}

var onceFunc = once(addByTwo);

console.log(onceFunc(4));  //should log 6
console.log(onceFunc(10));  //should log 6
console.log(onceFunc(9001));  //should log 6

This way you remove the function after first usage and you're just keeping the result.