Meryan
Meryan

Reputation: 1493

What's a good way to detect a method is called with different parameters?

Let us say we have a method we would like it to return the same last result, if none of its parameters have changed from the last invocation. How should we go about checking its parameters have not changed? Cache the parameters in an object? array? for later check.

Compute( p1:boolean, p2:number, p3:number) {
 // if any of p1 or p2 or p3 have changed from last invocation 
 // then redo computation
 // else return last result. 
}

In the past when dealing with a single parameter I have used a field like p1_last and compare to it on entry. something like this

  if (p1 == this.p1_last) {
    return this.result
  }
  else {
    this.p1_last = p1 // save p1 for next invocation.
    result = ....some algo....
    return this.result
  }

Your thoughts and suggested appreciated. Thank you.

Upvotes: 0

Views: 50

Answers (3)

Shivam Singla
Shivam Singla

Reputation: 2201

You can create a general function that memorizes the inputs for a function passed.

function memorize<F extends (...args: any) => any>(func: F): F {
  const cache = new Map()
  
  return function (this: unknown, ...args: unknown[]): unknown {
    // update the key calculation according to type of args
    const argsKey = args.toString()
    const cacheValue = cache.get(argsKey)
    
    if (cacheValue) console.log('cache working')
    if (cacheValue) return cacheValue
    
    const result = func.apply(this, args)
    cache.set(argsKey, result)
    
    return result
  } as F
}

let compute = function (p1: boolean, p2: number, p3: number) {
  // sample computation
  if (p1) return p2 * p3
  return p2 + p3
}

compute = memorize(compute)

let x = compute(true, 1, 2)
console.log(x)
x = compute(true, 1, 2) // cached
console.log(x)
x = compute(false, 1, 2)
console.log(x)
x = compute(false, 1, 2) // cached
console.log(x)
x = compute(false, 3, 2)
console.log(x)
x = compute(false, 3, 2) // cached
console.log(x)
x = compute(true, 1, 2) // cached
console.log(x)

Playground

Upvotes: 2

Meryan
Meryan

Reputation: 1493

How about

private ComputeLastParams = {}
private ResultLast 
Compute( p1:boolean, p2:number, p3:number) {
  if ( ObjectEqual ( {p1, p2, p3}, this.ComputeLastParams )
  ) {
    return this.ResultLast 
  }
  //
  this.ResultLast = /* some computation */
  this.ComputeLastParams = {p1, p2, p3}
  return this.ResultLast 
}
static ObjectEqual(object1, object2) {
        const keys1 = Object.keys(object1);
        const keys2 = Object.keys(object2);

        if (keys1.length !== keys2.length) {
            return false;
        }

        for (let key of keys1) {
            if (object1[key] !== object2[key]) {
                return false;
            }
        }

        return true;
    }

Upvotes: 0

CertainPerformance
CertainPerformance

Reputation: 371069

If the number of parameters is fixed, it should be trivial to check against an array:

let lastParams: [boolean, number, number];
let lastResult; // type this properly...
function Compute( p1:boolean, p2:number, p3:number) {
  if (
    lastParams &&
    lastParams[0] === p1 &&
    lastParams[1] === p2 &&
    lastParams[2] === p3
  ) {
    return lastResult;
  }
  lastResult = /* some computation */
  lastParams = [p1, p2, p3];
  return lastResult;
}

Upvotes: 3

Related Questions