Fundamentals 10 min read

First Encounter with Lazy List: Implementing Lazy Evaluation in JavaScript

The article explains Haskell‑style lazy lists, shows why lazy evaluation is useful, and walks through implementing lazy lists in JavaScript using custom classes, the ES6 iterable protocol, and generator functions, providing examples such as repeat, cycle, iterate, range and lazy operators like map, filter, take, and zip.

Youzan Coder
Youzan Coder
Youzan Coder
First Encounter with Lazy List: Implementing Lazy Evaluation in JavaScript

This article introduces the concept of lazy lists (Lazy List) and demonstrates how to implement lazy evaluation in JavaScript, drawing inspiration from Haskell's lazy evaluation paradigm.

The author begins by explaining Haskell's lazy evaluation through examples like repeat 1 (infinite list of 1s), cycle "abc" (repeating sequence), and the Sieve of Eratosthenes for generating prime numbers. In Haskell, these infinite structures are possible because the language uses lazy evaluation by default—unevaluated expressions remain as thunks in memory until actually needed.

The article then explores why lazy evaluation matters: it allows for more flexible code when working with indeterminate-length lists, enables on-demand computation (like reading large files piece by piece without loading the entire file into memory), and minimizes unnecessary calculations.

The core of the article demonstrates how to implement lazy lists in JavaScript using ES6 features:

1. Custom List Class : A simple implementation where head and tail can be either values or factory functions that produce values on demand.

2. Iterable Protocol : Using ES6's Iterable , Iterator , and IteratorResult interfaces to create lazy structures that only compute when next() is called.

3. Generator Functions : The most practical approach—generators provide a cleaner syntax for creating IterableIterator objects. The article shows implementations of:

repeat<T>(item: T) - infinite repetition

cycle<T>(items: Iterable<T>) - infinite cycling

iterate<T>(fn, initial) - iterative generation

range(start, end, step) - range generation

4. Operators : The article implements common list operations as lazy generators: map , filter , take , takeWhile , zip , and zipWith . A key helper function lift is introduced to convert any Iterable into an IterableIterator using the yield* operator.

The conclusion notes that while Generator and Iterator provide powerful lazy evaluation capabilities at the language level, they should be used judiciously—overuse can lead to memory overhead from cached thunks.

javascriptFunctional ProgrammingIteratorlazy-evaluationES6GeneratorInfinite List
Youzan Coder
Written by

Youzan Coder

Official Youzan tech channel, delivering technical insights and occasional daily updates from the Youzan tech team.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.