Infinite List Summary
InfiniteList Concept
- Represents potentially infinite sequences
- Lazily evaluated
- Uses head/tail structure
- Example:
class InfiniteList<T> { private final Producer<T> head; private final Producer<InfiniteList<T>> tail; public InfiniteList(Producer<T> head, Producer<InfiniteList<T>> tail) { this.head = head; this.tail = tail; } }
Creating Infinite Lists
-
Generate Method:
public static <T> InfiniteList<T> generate(Producer<T> producer) { return new InfiniteList<>(producer, () -> generate(producer)); }
-
Iterate Method:
public static <T> InfiniteList<T> iterate(T seed, Transformer<T,T> next) { return new InfiniteList<>(() -> seed, () -> iterate(next.transform(seed), next)); }
Operations on InfiniteList
- map: Transform elements
- filter: Select elements
- limit: Take first n elements
- Example:
InfiniteList<Integer> numbers = InfiniteList .iterate(0, x -> x + 1) // 0,1,2,3,... .filter(x -> x % 2 == 0) // 0,2,4,6,... .map(x -> x * x) // 0,4,16,36,... .limit(5); // first 5 elements
Lazy Evaluation Benefits
- Memory efficient
- Handles infinite sequences
- Computes only needed values
- Example:
InfiniteList<Integer> primes = InfiniteList .iterate(2, n -> n + 1) .filter(n -> isPrime(n)); // only checks primality when needed
Implementation Details
- Head and tail are producers
- Evaluation happens on demand
- Memoization for efficiency
- Example:
public T head() { return head.produce(); // evaluated only when called } public InfiniteList<T> tail() { return tail.produce(); // evaluated only when called }
Best Practices
- Use lazy operations
- Implement memoization
- Handle termination cases
- Consider memory usage
- Document infinite behavior
- Test with finite prefixes