Skip to content
  • Currying, Composition & Memoization · JavaScript

Currying, Composition & Memoization

LearnViaNotes @learnvianotes· 2 min read

Functional techniques built from closures and higher-order functions — and staple interview implementations.

Currying

JavaScript
function curry(fn) {
  return function curried(...args) {
    return args.length >= fn.length
      ? fn.apply(this, args)
      : (...more) => curried.apply(this, [...args, ...more]);
  };
}
const volume = (l, w, h) => l * w * h;
const cv = curry(volume);
console.log(cv(2)(3)(4), cv(2, 3)(4), cv(2)(3, 4), cv(2, 3, 4));

const log = curry((level, scope, msg) => `[${level}] ${scope}: ${msg}`);
const warnDb = log("WARN")("db");
console.log(warnDb("slow query"));
Output
24 24 24 24
[WARN] db: slow query

Infinite currying: sum(1)(2)(3)()

JavaScript
const sum = (a) => (b) => (b === undefined ? a : sum(a + b));
console.log(sum(1)(2)(3)(4)());
Output
10

Composition and pipe

JavaScript
const compose = (...fns) => (x) => fns.reduceRight((acc, f) => f(acc), x);
const pipe = (...fns) => (x) => fns.reduce((acc, f) => f(acc), x);

const trim = (s) => s.trim();
const lower = (s) => s.toLowerCase();
const slugify = (s) => s.replace(/\s+/g, "-");

console.log(pipe(trim, lower, slugify)("  Hello Big World "));
console.log(compose(slugify, lower, trim)("  Hello Big World "));
Output
hello-big-world
hello-big-world

Memoization

JavaScript
function memoize(fn, keyFn = (...args) => JSON.stringify(args)) {
  const cache = new Map();
  return function (...args) {
    const key = keyFn(...args);
    if (cache.has(key)) return cache.get(key);
    const result = fn.apply(this, args);
    cache.set(key, result);
    return result;
  };
}
let calls = 0;
const slowSquare = (n) => { calls++; return n * n; };
const fastSquare = memoize(slowSquare);
console.log(fastSquare(9), fastSquare(9), fastSquare(3), "calls:", calls);

const fib = memoize((n) => (n < 2 ? n : fib(n - 1) + fib(n - 2)));
console.log(fib(90));
Output
81 81 9 calls: 2
2880067194370816000

once, partial and friends

JavaScript
const partial = (fn, ...preset) => (...later) => fn(...preset, ...later);
const greet = (greeting, name) => `${greeting}, ${name}!`;
console.log(partial(greet, "Welcome")("Mei"));

const not = (pred) => (...args) => !pred(...args);
const isEven = (n) => n % 2 === 0;
console.log([1, 2, 3, 4].filter(not(isEven)));

const tap = (fn) => (x) => { fn(x); return x; };
console.log([1, 2].map(tap((x) => console.log("saw", x))));
Output
Welcome, Mei!
[ 1, 3 ]
saw 1
saw 2
[ 1, 2 ]

Implement a curry function.

What is memoization?

Free for students and teachers

Write notes like this one

Cards for every idea, quizzes and flashcards, read aloud — on the web and your phone.

Something wrong with this note? Open it to report