Generators written in imperative code, Iterators that implement the object-oriented Iterator pattern, and list processing (the core of LISP) share deep interconnections. They act as both creators and consumers of each other, enabling highly abstract programming while offering a prime example of how IP (Imperative Programming), OOP (Object-Oriented Programming), and FP (Functional Programming) can converge.
Below is a summary of the concepts covered in Chapters 1 and 2, viewed through the lens of Generator:Iterator:LISP = IP:OOP:FP.
- Iterator is the concrete implementation of the Iterator pattern.
- An iterator is an object that traverses collection-like data using a generalized pattern.
- Owing to its laziness, which evaluates values only when needed, it can handle not just finite collections but also infinite sequences.
- Generator creates iterators using imperative code.
- A generator function is a mechanism for building an iterator in an imperative code style.
- Because execution can pause and resume at
yield
, the generator’s code is effectively evaluated lazily in list-sized chunks. This aligns with the “code as list, list as code” perspective of LISP.
- Iterable Iterators can be handled imperatively, object-orientedly, or functionally.
- Imperatively, you can call
next()
directly inside awhile
loop or usefor...of
and spread (...
) to iterate. - Object-oriented approaches can encapsulate iterable iterators in a class or chain multiple iterators internally.
- Functionally, you can use higher-order functions (HOFs) to handle iterators by passing functions that process each element, implementing iteration logic through function composition while maximizing lazy evaluation and list processing.
- Multiple Ways to Create Iterators
- You can build an iterator yourself by directly implementing the Iterator interface, or can produce one imperatively via a generator function.
- You can also generate one in a functional style by combining list-processing based functions (to be examined in Chapter 3).
- Ultimately, iterators can be created in these three ways, each substitutable on a 1:1:1 basis:
- Imperative (IP) – Generating iterators with a generator
- Object-Oriented (OOP) – Directly implementing an iterator object
- Functional (FP) – Combining list-processing functions to produce an iterator
All this demonstrates how the iteration protocol serves as a linking bridge across various paradigms. In Chapter 3, we’ll focus specifically on handling iterators from a functional perspective and on lazy evaluation—expanding the Lisp-inspired idea of “code as lists” and examining how these multi-pronged approaches form the robust foundation of modern programming.