Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function to cache its argument's return value

I want to write a function once that accepts a callback as input and returns a function. When the returned function is called the first time, it should call the callback and return that output. If it is called any additional times, instead of calling the callback again it will simply return the output value from the first time it was called.

Below is what I have tried to do. But I am not getting the results as I expected. I need to understand this concept.

function once(func) {
    let num; 
    function retFunc(x){
        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
like image 498
Amit Kumar Avatar asked Jan 07 '19 07:01

Amit Kumar


People also ask

Is a form of caching where the return value of a function is cached based on its parameters?

Memoization is actually a specific type of caching. While caching can refer in general to any storing technique (like HTTP caching) for future use, memoizing specifically involves caching the return values of a function .

What does cache () do in Python?

Caching is an optimization technique that you can use in your applications to keep recent or often-used data in memory locations that are faster or computationally cheaper to access than their source.

Can caching work on any function?

cache can do much more (it works on function with any arguments, properties, any type of methods, and even classes...).


2 Answers

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));
like image 68
CertainPerformance Avatar answered Oct 17 '22 15:10

CertainPerformance


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.

like image 8
Mark Avatar answered Oct 17 '22 14:10

Mark