# Higher-Order Functions Pattern

## Problem

You find yourself writing similar loops that iterate over collections, applying slight variations of the same logic (filtering, transforming, accumulating). This leads to repetitive boilerplate code with the core logic buried inside loop bodies.

## Solution

Use **higher-order functions** -- functions that take other functions as arguments or return functions as results. The classic trio is `map` (transform each element), `filter` (select elements matching a predicate), and `reduce` (accumulate elements into a single value).

## When to Use

- Transforming, filtering, or aggregating collections
- Building data processing pipelines
- Anywhere you see repeated loop patterns differing only in the body
- Abstracting behavior to make code declarative

## When to Avoid

- When imperative loops are clearer for complex multi-step mutations
- Performance-critical hot paths where function call overhead matters
- When the team is unfamiliar with functional idioms (readability concern)

## Pseudocode

```
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

// Map: square each number
squared = map(numbers, x => x * x)

// Filter: keep only even numbers
evens = filter(numbers, x => x % 2 == 0)

// Reduce: sum all numbers
total = reduce(numbers, (acc, x) => acc + x, 0)

// Compose: sum of squares of even numbers
result = reduce(
    map(filter(numbers, x => x % 2 == 0), x => x * x),
    (acc, x) => acc + x,
    0
)
```

## Python

```python
from functools import reduce
from typing import Callable

def main() -> None:
    numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

    # Map: square each number
    squared = list(map(lambda x: x * x, numbers))
    print(f"Squared: {squared}")

    # Filter: keep even numbers
    evens = list(filter(lambda x: x % 2 == 0, numbers))
    print(f"Evens: {evens}")

    # Reduce: sum all numbers
    total = reduce(lambda acc, x: acc + x, numbers, 0)
    print(f"Sum: {total}")

    # Compose: sum of squares of even numbers
    result = reduce(
        lambda acc, x: acc + x,
        map(lambda x: x * x, filter(lambda x: x % 2 == 0, numbers)),
        0,
    )
    print(f"Sum of squares of evens: {result}")

    # Returning functions (function factory)
    def multiplier(factor: int) -> Callable[[int], int]:
        return lambda x: x * factor

    double = multiplier(2)
    triple = multiplier(3)
    print(f"Double 5: {double(5)}")
    print(f"Triple 5: {triple(5)}")

    # Chained pipeline using comprehensions (Pythonic style)
    pipeline_result = sum(x * x for x in numbers if x % 2 == 0)
    print(f"Pipeline (comprehension): {pipeline_result}")

if __name__ == "__main__":
    main()
```

## Go

```go
package main

import "fmt"

// Generic map function
func Map[T any, U any](slice []T, fn func(T) U) []U {
	result := make([]U, len(slice))
	for i, v := range slice {
		result[i] = fn(v)
	}
	return result
}

// Generic filter function
func Filter[T any](slice []T, predicate func(T) bool) []T {
	var result []T
	for _, v := range slice {
		if predicate(v) {
			result = append(result, v)
		}
	}
	return result
}

// Generic reduce function
func Reduce[T any, U any](slice []T, initial U, fn func(U, T) U) U {
	acc := initial
	for _, v := range slice {
		acc = fn(acc, v)
	}
	return acc
}

func main() {
	numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

	// Map: square each number
	squared := Map(numbers, func(x int) int { return x * x })
	fmt.Printf("Squared: %v\n", squared)

	// Filter: keep even numbers
	evens := Filter(numbers, func(x int) bool { return x%2 == 0 })
	fmt.Printf("Evens: %v\n", evens)

	// Reduce: sum all numbers
	total := Reduce(numbers, 0, func(acc, x int) int { return acc + x })
	fmt.Printf("Sum: %d\n", total)

	// Compose: sum of squares of even numbers
	result := Reduce(
		Map(
			Filter(numbers, func(x int) bool { return x%2 == 0 }),
			func(x int) int { return x * x },
		),
		0,
		func(acc, x int) int { return acc + x },
	)
	fmt.Printf("Sum of squares of evens: %d\n", result)

	// Function factory
	multiplier := func(factor int) func(int) int {
		return func(x int) int { return x * factor }
	}
	double := multiplier(2)
	triple := multiplier(3)
	fmt.Printf("Double 5: %d\n", double(5))
	fmt.Printf("Triple 5: %d\n", triple(5))
}
```

## JavaScript

```javascript
function main() {
  const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

  // Map: square each number
  const squared = numbers.map((x) => x * x);
  console.log("Squared:", squared);

  // Filter: keep even numbers
  const evens = numbers.filter((x) => x % 2 === 0);
  console.log("Evens:", evens);

  // Reduce: sum all numbers
  const total = numbers.reduce((acc, x) => acc + x, 0);
  console.log("Sum:", total);

  // Compose: sum of squares of even numbers
  const result = numbers
    .filter((x) => x % 2 === 0)
    .map((x) => x * x)
    .reduce((acc, x) => acc + x, 0);
  console.log("Sum of squares of evens:", result);

  // Function factory
  const multiplier = (factor) => (x) => x * factor;
  const double = multiplier(2);
  const triple = multiplier(3);
  console.log("Double 5:", double(5));
  console.log("Triple 5:", triple(5));

  // Pipe utility (compose left-to-right)
  const pipe =
    (...fns) =>
    (x) =>
      fns.reduce((v, f) => f(v), x);

  const processNumbers = pipe(
    (nums) => nums.filter((x) => x % 2 === 0),
    (nums) => nums.map((x) => x * x),
    (nums) => nums.reduce((a, b) => a + b, 0)
  );
  console.log("Piped result:", processNumbers(numbers));
}

main();
```

## Related Patterns

- **Currying** — currying transforms a multi-argument function into a chain of HOFs, each taking one argument.
- **Strategy** — a strategy passed as a function argument is a HOF-based alternative to the Strategy class pattern.
- **Monad** — monads use higher-order functions (bind/map) to chain computations in a composable way.
- **Decorator** — function decorators are higher-order functions that wrap and augment another function.
