or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

collections.mdfunctional-api.mdindex.mdsequences.mdutilities.md
tile.json

sequences.mddocs/

Sequences

Overview

Sequences represent lazy operations on collections, allowing efficient chaining of transformations without creating intermediate collections. Sequences are immutable and can be cached for performance.

Core Imports

import { Seq, Range, Repeat } from 'immutable';

Base Sequence Interface

abstract class Seq<K, V> implements Collection<K, V> {
  static <K, V>(collection: Collection<K, V>): Seq<K, V>;
  static <T>(collection: Iterable<T>): Seq.Indexed<T>;
  static <V>(obj: {[key: string]: V}): Seq.Keyed<string, V>;
  static isSeq(maybeSeq: unknown): maybeSeq is Seq<unknown, unknown>;
  
  // Properties
  size: number | undefined; // May be lazily computed or undefined
  
  // Force evaluation
  cacheResult(): Seq<K, V>;
  
  // All Collection methods inherited
}

Keyed Sequences

Sequences with key-value pairs, similar to Object iteration.

namespace Seq {
  class Keyed<K, V> extends Seq<K, V> {
    // Factory methods
    static <K, V>(collection?: Collection.Keyed<K, V>): Seq.Keyed<K, V>;
    static <V>(obj: {[key: string]: V}): Seq.Keyed<string, V>;
    
    // Conversion
    toJS(): {[key: string]: unknown};
    toJSON(): {[key: string]: V};
    toArray(): Array<[K, V]>;
    toSeq(): Seq.Keyed<K, V>;
    
    // Sequence operations
    concat(...collections: Array<Iterable<[K, V]> | {[key: string]: V}>): Seq.Keyed<K, V>;
    map<M>(mapper: (value: V, key: K, iter: this) => M, context?: unknown): Seq.Keyed<K, M>;
    mapKeys<M>(mapper: (key: K, value: V, iter: this) => M, context?: unknown): Seq.Keyed<M, V>;
    mapEntries<KM, VM>(mapper: (entry: [K, V], index: number, iter: this) => [KM, VM], context?: unknown): Seq.Keyed<KM, VM>;
    flatMap<KM, VM>(mapper: (value: V, key: K, iter: this) => Iterable<[KM, VM]>, context?: unknown): Seq.Keyed<KM, VM>;
    filter(predicate: (value: V, key: K, iter: this) => boolean, context?: unknown): Seq.Keyed<K, V>;
    partition(predicate: (value: V, key: K, iter: this) => boolean, context?: unknown): [Seq.Keyed<K, V>, Seq.Keyed<K, V>];
    flip(): Seq.Keyed<V, K>;
    
    // Iterator
    [Symbol.iterator](): IterableIterator<[K, V]>;
  }
}

Usage Examples

import { Seq } from 'immutable';

// Create from object
const keyedSeq = Seq.Keyed({ a: 1, b: 2, c: 3 });

// Lazy operations
const transformed = keyedSeq
  .map(value => value * 2)
  .filter(value => value > 2)
  .mapKeys(key => key.toUpperCase());

// Force evaluation
const result = transformed.toObject(); // { B: 4, C: 6 }

// Chain operations efficiently
const complex = Seq.Keyed({ x: 1, y: 2, z: 3 })
  .mapEntries(([key, value]) => [key + '_new', value * 10])
  .flip()
  .toMap(); // Map { 10: 'x_new', 20: 'y_new', 30: 'z_new' }

Indexed Sequences

Sequences with numeric indices, similar to Array iteration.

namespace Seq {
  class Indexed<T> extends Seq<number, T> {
    // Factory methods
    static <T>(collection?: Collection.Indexed<T>): Seq.Indexed<T>;
    static of<T>(...values: T[]): Seq.Indexed<T>;
    
    // Conversion
    toJS(): unknown[];
    toJSON(): T[];
    toArray(): T[];
    toSeq(): Seq.Indexed<T>;
    
    // Sequence operations
    concat(...valuesOrCollections: Array<T | Iterable<T>>): Seq.Indexed<T>;
    map<M>(mapper: (value: T, index: number, iter: this) => M, context?: unknown): Seq.Indexed<M>;
    flatMap<M>(mapper: (value: T, index: number, iter: this) => Iterable<M>, context?: unknown): Seq.Indexed<M>;
    filter(predicate: (value: T, index: number, iter: this) => boolean, context?: unknown): Seq.Indexed<T>;
    partition(predicate: (value: T, index: number, iter: this) => boolean, context?: unknown): [Seq.Indexed<T>, Seq.Indexed<T>];
    zip<U>(other: Collection<unknown, U>): Seq.Indexed<[T, U]>;
    zipAll<U>(other: Collection<unknown, U>): Seq.Indexed<[T, U]>;
    zipWith<U, Z>(zipper: (value: T, otherValue: U) => Z, otherCollection: Collection<unknown, U>): Seq.Indexed<Z>;
    
    // Iterator
    [Symbol.iterator](): IterableIterator<T>;
  }
}

Usage Examples

import { Seq } from 'immutable';

// Create from array
const indexedSeq = Seq.Indexed([1, 2, 3, 4, 5]);

// Lazy operations
const transformed = indexedSeq
  .map(x => x * x)
  .filter(x => x > 5)
  .take(3);

// Force evaluation
const result = transformed.toArray(); // [9, 16, 25]

// Zip operations
const seq1 = Seq.Indexed([1, 2, 3]);
const seq2 = Seq.Indexed(['a', 'b', 'c']);
const zipped = seq1.zip(seq2).toArray(); // [[1, 'a'], [2, 'b'], [3, 'c']]

// Custom zip function
const customZipped = seq1.zipWith((num, str) => `${num}-${str}`, seq2);
console.log(customZipped.toArray()); // ['1-a', '2-b', '3-c']

Set Sequences

Sequences with unique values, similar to Set iteration.

namespace Seq {
  class Set<T> extends Seq<T, T> {
    // Factory methods
    static <T>(collection?: Collection.Set<T>): Seq.Set<T>;
    static of<T>(...values: T[]): Seq.Set<T>;
    
    // Conversion
    toJS(): unknown[];
    toJSON(): T[];
    toArray(): T[];
    toSeq(): Seq.Set<T>;
    
    // Sequence operations
    concat(...collections: Array<Iterable<T>>): Seq.Set<T>;
    map<M>(mapper: (value: T, value2: T, iter: this) => M, context?: unknown): Seq.Set<M>;
    flatMap<M>(mapper: (value: T, value2: T, iter: this) => Iterable<M>, context?: unknown): Seq.Set<M>;
    filter(predicate: (value: T, value2: T, iter: this) => boolean, context?: unknown): Seq.Set<T>;
    partition(predicate: (value: T, value2: T, iter: this) => boolean, context?: unknown): [Seq.Set<T>, Seq.Set<T>];
    
    // Iterator
    [Symbol.iterator](): IterableIterator<T>;
  }
}

Usage Examples

import { Seq, Set } from 'immutable';

// Create from Set or array with duplicates
const setSeq = Seq.Set([1, 2, 2, 3, 3, 4]);

// Lazy operations maintain uniqueness
const transformed = setSeq
  .map(x => x * 2)
  .filter(x => x > 4);

// Force evaluation
const result = transformed.toArray(); // [6, 8]

// Convert to other collections
const backToSet = transformed.toSet(); // Set { 6, 8 }
const toList = transformed.toList(); // List [ 6, 8 ]

Range

Creates sequences of numbers.

function Range(start?: number, end?: number, step?: number): Seq.Indexed<number>;

Parameters

  • start (optional): Starting number (default: 0)
  • end (optional): Ending number (exclusive, default: Infinity)
  • step (optional): Step size (default: 1)

Usage Examples

import { Range } from 'immutable';

// Basic ranges
const range1 = Range(10); // [0, 1, 2, ..., 9]
const range2 = Range(5, 10); // [5, 6, 7, 8, 9]
const range3 = Range(0, 10, 2); // [0, 2, 4, 6, 8]

// Infinite sequences (be careful!)
const infinite = Range(0); // [0, 1, 2, 3, ...]
const first5 = infinite.take(5).toArray(); // [0, 1, 2, 3, 4]

// Reverse ranges
const reverse = Range(10, 0, -1); // [10, 9, 8, ..., 1]

// Complex operations
const processed = Range(1, 100)
  .filter(n => n % 2 === 0)
  .map(n => n * n)
  .take(5)
  .toArray(); // [4, 16, 36, 64, 100]

Repeat

Creates sequences of repeated values.

function Repeat<T>(value: T, times?: number): Seq.Indexed<T>;

Parameters

  • value: The value to repeat
  • times (optional): Number of repetitions (default: Infinity)

Usage Examples

import { Repeat } from 'immutable';

// Finite repetition
const repeat1 = Repeat('hello', 3); // ['hello', 'hello', 'hello']
const repeat2 = Repeat(42, 5); // [42, 42, 42, 42, 42]

// Infinite repetition (be careful!)
const infinite = Repeat('x'); // ['x', 'x', 'x', ...]
const first3 = infinite.take(3).toArray(); // ['x', 'x', 'x']

// Complex values
const complexRepeat = Repeat({ id: 1, name: 'test' }, 2);
const result = complexRepeat.toArray(); // [{ id: 1, name: 'test' }, { id: 1, name: 'test' }]

// With transformations
const transformed = Repeat(1, 5)
  .map((val, index) => val + index)
  .toArray(); // [1, 2, 3, 4, 5]

Lazy Evaluation and Caching

Sequences are evaluated lazily, meaning operations are not performed until the sequence is consumed:

interface Seq<K, V> {
  cacheResult(): Seq<K, V>;
}

Usage Examples

import { Seq } from 'immutable';

// Operations are not executed until consumption
const lazySeq = Seq([1, 2, 3, 4, 5])
  .map(x => {
    console.log(`Processing ${x}`); // Not executed yet
    return x * 2;
  })
  .filter(x => x > 5);

// Force evaluation and cache result
const cached = lazySeq.cacheResult();

// Multiple consumptions use cached result
const array1 = cached.toArray(); // Logs: Processing 1, 2, 3, 4, 5
const array2 = cached.toArray(); // No logging, uses cached result

// Without caching, each consumption re-evaluates
const uncached = Seq([1, 2, 3]).map(x => x * 2);
const result1 = uncached.toArray(); // Evaluates
const result2 = uncached.toArray(); // Evaluates again

Sequence Conversion

Sequences can be converted to collections or JavaScript types:

interface Seq<K, V> {
  // To Collections
  toList(): List<V>;
  toMap(): Map<K, V>;
  toOrderedMap(): OrderedMap<K, V>;
  toSet(): Set<V>;
  toOrderedSet(): OrderedSet<V>;
  toStack(): Stack<V>;
  
  // To JavaScript
  toJS(): unknown;
  toJSON(): unknown;
  toArray(): unknown[];
  toObject(): {[key: string]: V};
}

Usage Examples

import { Seq, List, Map, Set } from 'immutable';

const seq = Seq({ a: 1, b: 2, c: 3 })
  .map(value => value * 2)
  .filter(value => value > 2);

// Convert to different collection types
const list = seq.toList(); // List [ 4, 6 ]
const map = seq.toMap(); // Map { "b" => 4, "c" => 6 }
const set = seq.valueSeq().toSet(); // Set { 4, 6 }

// Convert to JavaScript types
const obj = seq.toObject(); // { b: 4, c: 6 }
const arr = seq.entrySeq().toArray(); // [['b', 4], ['c', 6]]
const js = seq.toJS(); // { b: 4, c: 6 }

Performance Considerations

Sequences are designed for efficient chaining:

import { List, Seq } from 'immutable';

const list = List([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);

// Inefficient: Creates intermediate collections
const inefficient = list
  .map(x => x * 2)        // Creates new List
  .filter(x => x > 10)    // Creates new List
  .take(3);               // Creates new List

// Efficient: Uses lazy evaluation
const efficient = list
  .toSeq()                // Convert to Seq
  .map(x => x * 2)        // Lazy operation
  .filter(x => x > 10)    // Lazy operation
  .take(3)                // Lazy operation
  .toList();              // Single evaluation

// Even more efficient for one-time use
const oneTime = Seq(list)
  .map(x => x * 2)
  .filter(x => x > 10)
  .take(3)
  .toArray();             // Direct to JavaScript array