Partial Application & Currying

Hard

Partial application fixes some arguments of a function, producing another function with fewer parameters. Currying transforms a function with multiple arguments into a sequence of functions each taking a single argument. These functional programming techniques leverage closures to create specialized functions and enable function composition patterns.

Interactive Visualization

CodeCreation Phase
1function outer() {
2 let x = 10;
3 function inner() {
4 return x;
5 }
6 return inner;
7}
8
9const fn = outer();
10fn(); // 10
Call Stack
Global EC
Variables:
fnundefined
Heap Memory
(empty)
Output
Global EC created - outer function is defined
1 / 6
Key Insight: A closure is formed when an inner function is returned from an outer function, maintaining access to the outer function's variables even after the outer function has completed.

Key Points

  • Partial application: fix some arguments, return function for rest
  • Currying: f(a,b,c) => f(a)(b)(c)
  • Both use closures to remember fixed arguments
  • Useful for creating specialized functions
  • Enables point-free style (tacit programming)

Code Examples

Partial Application

function partial(fn, ...fixedArgs) {
  return function(...remainingArgs) {
    return fn(...fixedArgs, ...remainingArgs);
  };
}

// Or with bind
function greet(greeting, name) {
  return `${greeting}, ${name}!`;
}

const sayHello = partial(greet, "Hello");
const sayHi = greet.bind(null, "Hi");

console.log(sayHello("Alice"));  // "Hello, Alice!"
console.log(sayHi("Bob"));       // "Hi, Bob!"

// Practical: logger with prefix
function log(level, message) {
  console.log(`[${level}] ${message}`);
}

const logError = partial(log, "ERROR");
const logInfo = partial(log, "INFO");

logError("File not found");  // [ERROR] File not found
logInfo("Server started");    // [INFO] Server started

Partial application fixes some arguments, returning a function that takes the rest.

Currying

// Transform f(a, b, c) to f(a)(b)(c)
function curry(fn) {
  return function curried(...args) {
    if (args.length >= fn.length) {
      return fn.apply(this, args);
    } else {
      return function(...nextArgs) {
        return curried.apply(this, args.concat(nextArgs));
      };
    }
  };
}

// Usage
const add = curry((a, b, c) => a + b + c);

console.log(add(1)(2)(3));  // 6
console.log(add(1, 2)(3));  // 6
console.log(add(1)(2, 3));  // 6
console.log(add(1, 2, 3));  // 6

// Create specialized functions
const add10 = add(10);
const add10and5 = add10(5);
console.log(add10and5(3));  // 18

Currying transforms multi-argument functions into nested single-argument functions using closures.

Common Mistakes

  • Confusing partial application with currying
  • Not handling this context when currying methods
  • Over-engineering simple functions

Interview Tips

  • Know the difference: partial fixes N args, curry transforms to single-arg chain
  • Know bind() for simple partial application
  • Show practical use cases (logging, validation)