# Lazy Evaluation, Generators and Iterators — Functional Programming Concepts

Source: https://www.geekswithgeeks.com/en/functional-programming/rc-lazy

> Compute values only when they are needed.

## Eager versus lazy

**Eager** evaluation computes values immediately; `array.map(f).filter(g)` builds a full intermediate array at each step. **Lazy** evaluation delays work until a value is requested, which allows infinite sequences and stops early when only a few results are needed. Haskell is lazy by default. JavaScript gets laziness from **generators** (`function*` with `yield`) and the iterator protocol; Python from generators and `itertools`. Newer JavaScript engines also provide iterator helpers such as `Iterator.prototype.map` and `take`; check support for your runtime. The trade-off: laziness makes the timing of work, and of any side effects, harder to predict.

## Lazy pipelines with generators

Only as many values as requested are ever computed.

```typescript
function* naturals(): Generator<number> {
  let n = 1;
  while (true) yield n++;          // infinite, but lazy
}

function* mapIter<A, B>(xs: Iterable<A>, f: (a: A) => B) {
  for (const x of xs) yield f(x);
}
function* filterIter<A>(xs: Iterable<A>, p: (a: A) => boolean) {
  for (const x of xs) if (p(x)) yield x;
}
function* take<A>(xs: Iterable<A>, n: number) {
  if (n <= 0) return;
  for (const x of xs) {
    yield x;
    if (--n === 0) return;
  }
}

const firstFiveEvenSquares = [
  ...take(filterIter(mapIter(naturals(), n => n * n), n => n % 2 === 0), 5),
];
// [4, 16, 36, 64, 100]; the infinite source is pulled only as far as needed
```

## The same idea elsewhere

Python: `itertools.islice((n * n for n in itertools.count(1) if n % 2 == 0), 5)`. Haskell: `take 5 (filter even (map (^2) [1..]))` works directly because lists are lazy.

**Quiz:** What does lazy evaluation make possible?

- [ ] Avoiding the need for functions
- [ ] Guaranteed faster code in every case
- [ ] Running side effects in a predictable order
- [x] Working with infinite sequences and stopping as soon as enough results exist

*Answer:* Working with infinite sequences and stopping as soon as enough results exist. Work happens on demand.
