Functions as Values

Lesson 3: Functions as Values

In functional programming, functions are first-class citizens: you can store them in variables, pass them as arguments, and return them from other functions. Once this clicks, your code stops being a list of instructions and becomes a composition of behaviors.

Higher-Order Functions

A higher-order function is any function that takes another function as input, returns one, or both. The three you'll meet constantly are map, filter, and reduce:

const numbers = [1, 2, 3, 4, 5, 6];

// map: transform every element
const doubled = numbers.map(n => n * 2);
// [2, 4, 6, 8, 10, 12]

// filter: keep elements that pass a test
const evens = numbers.filter(n => n % 2 === 0);
// [2, 4, 6]

// reduce: fold the whole list into a single value
const sum = numbers.reduce((acc, n) => acc + n, 0);
// 21

Notice what's missing: no for loop, no index variable, no accumulator you mutate by hand. You describe what transformation you want; the library handles how to walk the array.

Loop vs map: A for-loop is a recipe for mutating an accumulator. map/filter/reduce are declarative โ€” they state the transformation and hand the mechanics to the runtime. Same result, radically different clarity.
[1,2,3,4,5,6] filter even keeps 3 of 6 [2,4,6] map ร—2 [4,8,12] each stage is a pure function โ€” the array only flows forward

Closures

A closure is a function that "remembers" the variables from the scope where it was created, even after that scope has finished running:

function makeAdder(x) {
  return function(y) {
    return x + y;   // x is captured from the outer scope
  };
}

const add5 = makeAdder(5);
add5(10);  // 15
add5(3);   // 8

Closures are how FP does "configuration": you build a specialized function once (like add5) and pass it around as a value. No class, no object, no state mutation needed.

Passing Behavior Around

Because functions are values, they become the natural currency of your code:

  • Callbacks: event handlers, request handlers, timeout callbacks.
  • Strategy injection: pass a sort function, a comparison function, a formatter.
  • Partial application: pre-fill some arguments to build a specialized version of a general function.
Payoff: In OOP you often create an object just to carry one piece of behavior (a "strategy object"). In FP you just pass the function. Less ceremony, same power.

๐Ÿง  Knowledge Check

1. What does [1, 2, 3].map(n => n * 10) produce?

2. A higher-order function is one that:

3. A closure is:

Further Reading