or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

array-operations.mdcollection-types.mderror-types.mdindex.mditerator-helpers.mdmath-utilities.mdobject-methods.mdpromise-utilities.mdreflection-api.mdstring-processing.mdsymbol-management.mdtypedarray-operations.mdweb-apis.md
tile.json

iterator-helpers.mddocs/

Iterator Helpers

Iterator protocol enhancements with functional programming methods for transforming, filtering, and consuming iterators efficiently.

Capabilities

Iterator Constructor and Protocol

Core Iterator functionality and protocol implementation for creating custom iterators.

/**
 * Iterator constructor and protocol
 */
interface IteratorConstructor {
  /**
   * Creates a new Iterator
   */
  new (): Iterator<any>;
  
  /**
   * Concatenates multiple iterables into a single iterator
   * @param iterables - Iterables to concatenate
   */
  concat<T>(...iterables: Iterable<T>[]): Iterator<T>;
}

interface Iterator<T, TReturn = any, TNext = undefined> {
  /**
   * Gets the next value from the iterator
   * @param value - Optional value to pass to the iterator
   */
  next(...args: [] | [TNext]): IteratorResult<T, TReturn>;
  
  /**
   * Optional return method for cleanup
   * @param value - Return value
   */
  return?(value?: TReturn): IteratorResult<T, TReturn>;
  
  /**
   * Optional throw method for error handling
   * @param e - Error to throw
   */
  throw?(e?: any): IteratorResult<T, TReturn>;
}

interface IteratorResult<T, TReturn = any> {
  done: boolean;
  value: T | TReturn;
}

Usage Examples:

import Iterator from 'core-js-pure/stable/iterator';

// Custom iterator implementation
class RangeIterator extends Iterator {
  constructor(start, end, step = 1) {
    super();
    this.current = start;
    this.end = end;
    this.step = step;
  }
  
  next() {
    if (this.current < this.end) {
      const value = this.current;
      this.current += this.step;
      return { value, done: false };
    }
    return { done: true };
  }
}

// Using custom iterator
const range = new RangeIterator(0, 10, 2);
console.log([...range]); // [0, 2, 4, 6, 8]

// Generator function (built-in iterator)
function* fibonacci() {
  let a = 0, b = 1;
  while (true) {
    yield a;
    [a, b] = [b, a + b];
  }
}

const fib = fibonacci();
console.log(fib.next().value); // 0
console.log(fib.next().value); // 1
console.log(fib.next().value); // 1
console.log(fib.next().value); // 2

Iterator Transformation Methods

Methods for transforming iterator values through mapping and filtering operations.

interface Iterator<T> {
  /**
   * Creates iterator that applies mapping function to each value
   * @param mapperFn - Function to transform each value
   */
  map<U>(mapperFn: (value: T, index: number) => U): Iterator<U>;
  
  /**
   * Creates iterator that filters values based on predicate
   * @param filtererFn - Function to test each value
   */
  filter(filtererFn: (value: T, index: number) => boolean): Iterator<T>;
  
  /**
   * Creates iterator that maps values and flattens results
   * @param mapperFn - Function that returns an iterable for each value
   */
  flatMap<U>(mapperFn: (value: T, index: number) => Iterable<U>): Iterator<U>;
}

Usage Examples:

import Iterator from 'core-js-pure/stable/iterator';

// Iterator transformations
function* numbers() {
  for (let i = 1; i <= 10; i++) {
    yield i;
  }
}

// Map transformation
const doubled = numbers().map(x => x * 2);
console.log([...doubled]); // [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

// Filter transformation
const evens = numbers().filter(x => x % 2 === 0);
console.log([...evens]); // [2, 4, 6, 8, 10]

// Chain transformations
const processedNumbers = numbers()
  .filter(x => x > 3)
  .map(x => x * x)
  .filter(x => x < 50);

console.log([...processedNumbers]); // [16, 25, 36, 49]

// FlatMap for nested iteration
function* words() {
  yield 'hello';
  yield 'world';
}

const chars = words().flatMap(word => [...word]);
console.log([...chars]); // ['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd']

// Practical example: process file lines
function* fileLines() {
  yield 'name,age,city';
  yield 'Alice,25,NYC';
  yield 'Bob,30,LA';
}

const csvData = fileLines()
  .filter(line => !line.startsWith('name')) // Skip header
  .map(line => line.split(','))
  .map(([name, age, city]) => ({ name, age: parseInt(age), city }));

console.log([...csvData]);
// [{ name: 'Alice', age: 25, city: 'NYC' }, { name: 'Bob', age: 30, city: 'LA' }]

Iterator Reduction and Aggregation

Methods for reducing iterators to single values or testing conditions.

interface Iterator<T> {
  /**
   * Reduces iterator to single value using reducer function
   * @param reducerFn - Function to combine values
   * @param initialValue - Initial value for accumulator
   */
  reduce<U>(reducerFn: (accumulator: U, currentValue: T, index: number) => U, initialValue: U): U;
  reduce(reducerFn: (accumulator: T, currentValue: T, index: number) => T): T;
  
  /**
   * Tests whether all values satisfy the predicate
   * @param predicate - Function to test each value
   */
  every(predicate: (value: T, index: number) => boolean): boolean;
  
  /**
   * Tests whether any value satisfies the predicate
   * @param predicate - Function to test each value
   */
  some(predicate: (value: T, index: number) => boolean): boolean;
  
  /**
   * Finds first value that satisfies the predicate
   * @param predicate - Function to test each value
   */
  find(predicate: (value: T, index: number) => boolean): T | undefined;
}

Usage Examples:

import Iterator from 'core-js-pure/stable/iterator';

function* numbers() {
  for (let i = 1; i <= 5; i++) {
    yield i;
  }
}

// Reduce to single value
const sum = numbers().reduce((acc, val) => acc + val, 0);
console.log(sum); // 15

const product = numbers().reduce((acc, val) => acc * val);
console.log(product); // 120

// Testing conditions
const allPositive = numbers().every(x => x > 0);
console.log(allPositive); // true

const anyEven = numbers().some(x => x % 2 === 0);
console.log(anyEven); // true

const firstLarge = numbers().find(x => x > 3);
console.log(firstLarge); // 4

// Complex reduction example
function* transactions() {
  yield { type: 'deposit', amount: 100 };
  yield { type: 'withdrawal', amount: 30 };
  yield { type: 'deposit', amount: 50 };
  yield { type: 'withdrawal', amount: 20 };
}

const accountSummary = transactions().reduce(
  (summary, transaction) => {
    if (transaction.type === 'deposit') {
      summary.balance += transaction.amount;
      summary.deposits += transaction.amount;
    } else {
      summary.balance -= transaction.amount;
      summary.withdrawals += transaction.amount;
    }
    summary.transactionCount++;
    return summary;
  },
  { balance: 0, deposits: 0, withdrawals: 0, transactionCount: 0 }
);

console.log(accountSummary);
// { balance: 100, deposits: 150, withdrawals: 50, transactionCount: 4 }

Iterator Slicing and Limiting

Methods for controlling the number of values taken from iterators.

interface Iterator<T> {
  /**
   * Creates iterator that yields first N values
   * @param limit - Number of values to take
   */
  take(limit: number): Iterator<T>;
  
  /**
   * Creates iterator that skips first N values
   * @param limit - Number of values to skip
   */
  drop(limit: number): Iterator<T>;
}

Usage Examples:

import Iterator from 'core-js-pure/stable/iterator';

function* infiniteNumbers() {
  let i = 0;
  while (true) {
    yield i++;
  }
}

// Take first N values
const firstTen = infiniteNumbers().take(10);
console.log([...firstTen]); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

// Skip first N values
const skipFirst = infiniteNumbers().drop(5).take(5);
console.log([...skipFirst]); // [5, 6, 7, 8, 9]

// Pagination pattern
const paginate = (iterator, pageSize, pageNumber) => {
  return iterator
    .drop(pageSize * (pageNumber - 1))
    .take(pageSize);
};

function* users() {
  for (let i = 1; i <= 100; i++) {
    yield { id: i, name: `User ${i}` };
  }
}

// Get page 3 with 10 users per page
const page3 = paginate(users(), 10, 3);
console.log([...page3]); // Users 21-30

// Batch processing
const processBatches = (iterator, batchSize) => {
  const batches = [];
  let batch = [...iterator.take(batchSize)];
  
  while (batch.length > 0) {
    batches.push(batch);
    batch = [...iterator.take(batchSize)];
  }
  
  return batches;
};

Iterator Consumption Methods

Methods for consuming entire iterators and converting to other data structures.

interface Iterator<T> {
  /**
   * Converts iterator to array
   */
  toArray(): T[];
  
  /**
   * Converts iterator to async iterator
   */
  toAsync(): AsyncIterator<T>;
  
  /**
   * Executes function for each value in iterator
   * @param callbackFn - Function to execute for each value
   */
  forEach(callbackFn: (value: T, index: number) => void): void;
}

Usage Examples:

import Iterator from 'core-js-pure/stable/iterator';

function* colors() {
  yield 'red';
  yield 'green';
  yield 'blue';
}

// Convert to array
const colorArray = colors().toArray();
console.log(colorArray); // ['red', 'green', 'blue']

// Process each value
colors().forEach((color, index) => {
  console.log(`Color ${index}: ${color}`);
});
// Color 0: red
// Color 1: green
// Color 2: blue

// Chaining with consumption
function* numbers() {
  for (let i = 1; i <= 20; i++) {
    yield i;
  }
}

const processedArray = numbers()
  .filter(x => x % 2 === 0)
  .map(x => x * x)
  .take(5)
  .toArray();

console.log(processedArray); // [4, 16, 36, 64, 100]

// Side effects with forEach
const logAndCollect = (iterator) => {
  const results = [];
  iterator.forEach(value => {
    console.log(`Processing: ${value}`);
    results.push(value);
  });
  return results;
};

Iterator Resource Management

Methods for proper cleanup and disposal of iterators.

interface Iterator<T> {
  /**
   * Disposes the iterator and releases resources
   */
  dispose(): void;
}

Usage Examples:

import Iterator from 'core-js-pure/stable/iterator';

// Iterator with cleanup
class FileLineIterator extends Iterator {
  constructor(filename) {
    super();
    this.filename = filename;
    this.fileHandle = null; // Simulated file handle
    this.lines = ['line 1', 'line 2', 'line 3']; // Mock data
    this.index = 0;
  }
  
  next() {
    if (this.index < this.lines.length) {
      return { value: this.lines[this.index++], done: false };
    }
    return { done: true };
  }
  
  dispose() {
    if (this.fileHandle) {
      console.log(`Closing file: ${this.filename}`);
      this.fileHandle = null;
    }
  }
}

// Using with automatic disposal
const processFile = (filename) => {
  const iterator = new FileLineIterator(filename);
  
  try {
    const lines = iterator
      .filter(line => line.length > 0)
      .map(line => line.trim())
      .toArray();
    
    return lines;
  } finally {
    iterator.dispose(); // Ensure cleanup
  }
};

// Resource management pattern
const withIterator = (createIterator, processor) => {
  const iterator = createIterator();
  try {
    return processor(iterator);
  } finally {
    if (iterator.dispose) {
      iterator.dispose();
    }
  }
};

const result = withIterator(
  () => new FileLineIterator('data.txt'),
  (iterator) => iterator.map(line => line.toUpperCase()).toArray()
);

Common Patterns

Lazy Data Processing Pipeline

Building efficient data processing pipelines with lazy evaluation.

import Iterator from 'core-js-pure/stable/iterator';

// Lazy CSV processor
class CSVProcessor {
  constructor(data) {
    this.data = data;
  }
  
  *[Symbol.iterator]() {
    for (const line of this.data) {
      yield line;
    }
  }
  
  // Fluent interface for chaining
  filter(predicate) {
    return new CSVProcessor(
      (function* (data) {
        let index = 0;
        for (const item of data) {
          if (predicate(item, index++)) {
            yield item;
          }
        }
      })(this)
    );
  }
  
  map(mapper) {
    return new CSVProcessor(
      (function* (data) {
        let index = 0;
        for (const item of data) {
          yield mapper(item, index++);
        }
      })(this)
    );
  }
  
  take(count) {
    return new CSVProcessor(
      (function* (data) {
        let taken = 0;
        for (const item of data) {
          if (taken >= count) break;
          yield item;
          taken++;
        }
      })(this)
    );
  }
  
  toArray() {
    return [...this];
  }
}

// Usage
const csvData = [
  'name,age,city',
  'Alice,25,NYC',
  'Bob,30,LA',
  'Charlie,35,Chicago',
  'Diana,28,Boston'
];

const result = new CSVProcessor(csvData)
  .filter(line => !line.startsWith('name')) // Skip header
  .map(line => {
    const [name, age, city] = line.split(',');
    return { name, age: parseInt(age), city };
  })
  .filter(person => person.age > 27)
  .take(2)
  .toArray();

console.log(result);
// [{ name: 'Bob', age: 30, city: 'LA' }, { name: 'Charlie', age: 35, city: 'Chicago' }]

Infinite Sequence Generation

Creating and working with infinite sequences using iterators.

import Iterator from 'core-js-pure/stable/iterator';

// Mathematical sequences
const sequences = {
  *fibonacci() {
    let [a, b] = [0, 1];
    while (true) {
      yield a;
      [a, b] = [b, a + b];
    }
  },
  
  *primes() {
    yield 2;
    const primes = [2];
    let candidate = 3;
    
    while (true) {
      const isPrime = !primes.some(p => 
        p * p <= candidate && candidate % p === 0
      );
      
      if (isPrime) {
        primes.push(candidate);
        yield candidate;
      }
      candidate += 2;
    }
  },
  
  *collatz(n) {
    while (n !== 1) {
      yield n;
      n = n % 2 === 0 ? n / 2 : 3 * n + 1;
    }
    yield 1;
  }
};

// Use infinite sequences
const firstTenFib = [...sequences.fibonacci().take(10)];
console.log(firstTenFib); // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

const primesUnder100 = [...sequences.primes().filter(p => p < 100)];
console.log(primesUnder100);

const collatzSequence = [...sequences.collatz(7)];
console.log(collatzSequence); // [7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]

Event Stream Processing

Processing event streams using iterator helpers.

import Iterator from 'core-js-pure/stable/iterator';

// Mock event stream
class EventStream extends Iterator {
  constructor() {
    super();
    this.events = [
      { type: 'click', x: 100, y: 200, timestamp: 1000 },
      { type: 'mousemove', x: 105, y: 205, timestamp: 1100 },
      { type: 'click', x: 110, y: 210, timestamp: 1200 },
      { type: 'keypress', key: 'a', timestamp: 1300 },
      { type: 'click', x: 115, y: 215, timestamp: 1400 }
    ];
    this.index = 0;
  }
  
  next() {
    if (this.index < this.events.length) {
      return { value: this.events[this.index++], done: false };
    }
    return { done: true };
  }
}

// Event processing pipeline
const processEvents = (eventStream) => {
  return eventStream
    .filter(event => event.type === 'click')
    .map(event => ({
      ...event,
      position: `${event.x},${event.y}`,
      relativeTime: event.timestamp - 1000
    }))
    .filter(event => event.relativeTime < 300);
};

const clicks = processEvents(new EventStream()).toArray();
console.log(clicks);
// Filtered and transformed click events within time window