Skip to content

Instantly share code, notes, and snippets.

@sebinsua
Last active August 14, 2022 20:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sebinsua/92ee597b1c28465520ed7b25de02cead to your computer and use it in GitHub Desktop.
Save sebinsua/92ee597b1c28465520ed7b25de02cead to your computer and use it in GitHub Desktop.
function defaultCreateKey(args) {
return JSON.stringify(args);
}
class LruCache {
constructor(capacity = Infinity) {
this.capacity = capacity;
this.cache = new Map();
}
has(key) {
return this.cache.has(key);
}
get(key) {
const value = this.cache.get(key);
this.cache.delete(key);
this.cache.set(key, value);
return value;
}
set(key, value) {
if (this.cache.size + 1 > this.capacity) {
const key = this._getLeastRecentlyUsedKey();
if (key) {
// console.log("evicting key:", key);
this.cache.delete(key);
}
}
this.cache.delete(key);
this.cache.set(key, value);
}
_getLeastRecentlyUsedKey() {
for (const [key] of this.cache) {
return key;
}
return undefined;
}
}
function memoize(
fn,
{
createKey = defaultCreateKey,
size = Infinity,
cache = new LruCache(size)
} = {}
) {
return (...args) => {
const key = createKey(args);
if (cache.has(key)) {
return cache.get(key);
}
cache.set(key, fn(...args));
return cache.get(key);
};
}
const newFn = memoize((key) => Math.random(), { size: 3 });
for (let key of [
"key",
"key2",
"key3",
"key",
"key2",
"key4",
"key5",
"key3",
"key",
"key5"
]) {
console.log(key, newFn(key));
}
@sebinsua
Copy link
Author

sebinsua commented Aug 14, 2022

Not using an LRU below but have shown a way of referrring to the inner function as a memoized function internally without needinig to know its memoized name.

let calls = 0;

function fib(n) {
  calls += 1;

  if (n === 0) {
    return 0;
  }
  if (n === 1) {
    return 1;
  }

  return fib(n - 1) + fib(n - 2);
}

function memoize(createFn) {
  const produceKey = (args) => args.join(" ");

  const results = new Map();

  const fn = createFn(memoizedFn);

  function memoizedFn(...args) {
    const key = produceKey(args);

    if (results.has(key)) {
      return results.get(key);
    }

    const value = fn(...args);

    results.set(key, value);

    return value;
  }

  return memoizedFn;
}

const memoFib = memoize(
  (selfFn) =>
    function fib(n) {
      calls += 1;

      if (n === 0) {
        return 0;
      }
      if (n === 1) {
        return 1;
      }

      return selfFn(n - 1) + selfFn(n - 2);
    }
);

function iterativeFib(n) {
  let a = 0;
  let b = 1;

  let i = 0;
  while (i++ < n) {
    [a, b] = [b, a + b];
  }

  return a;
}

for (let c of [
  0,
  1,
  2,
  3,
  4,
  5,
  6,
  7,
  8,
  9,
  10,
  11,
  12,
  13,
  14,
  15,
  16,
  17,
  18,
  19,
  20
]) {
  calls = 0;
  console.log(`fib(${c}): `, fib(c), ` caused ${calls} calls`);
}

for (let c of [
  0,
  1,
  2,
  3,
  4,
  5,
  6,
  7,
  8,
  9,
  10,
  11,
  12,
  13,
  14,
  15,
  16,
  17,
  18,
  19,
  20
]) {
  calls = 0;
  console.log(`memoFib(${c}): `, memoFib(c), ` caused ${calls} calls`);
}

for (let c of [
  0,
  1,
  2,
  3,
  4,
  5,
  6,
  7,
  8,
  9,
  10,
  11,
  12,
  13,
  14,
  15,
  16,
  17,
  18,
  19,
  20
]) {
  console.log(`iterativeFib(${c}): `, iterativeFib(c));
}

See: https://codesandbox.io/s/vigilant-cerf-mbtyky?file=%2Fsrc%2Findex.js

(I learn this from: https://raganwald.com/2018/09/10/why-y.html)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment