MutableList.ts
MutableList.ts overview
Section titled “MutableList.ts overview”Mutable lists for collecting ordered values and draining them from the front.
A MutableList<A> can append values to the end, prepend values to the
beginning, take one or more values from the front, inspect its contents as an
array, filter values, remove values, and clear itself. All operations update
the same list object in place and keep its length field current. Taking
from an empty list returns the Empty symbol.
Since v4.0.0
Exports Grouped by Category
Section titled “Exports Grouped by Category”constructors
Section titled “constructors”Creates an empty MutableList.
Example (Creating an empty mutable list)
import { MutableList } from "effect"
const list = MutableList.make<string>()
// Add elementsMutableList.append(list, "first")MutableList.append(list, "second")MutableList.prepend(list, "beginning")
console.log(list.length) // 3
// Take elements in FIFO order (from head)console.log(MutableList.take(list)) // "beginning"console.log(MutableList.take(list)) // "first"console.log(MutableList.take(list)) // "second"Signature
declare const make: <A>() => MutableList<A>Since v2.0.0
elements
Section titled “elements”Takes a single element from the beginning of the MutableList. Returns the element if available, or the Empty symbol if the list is empty. The taken element is removed from the list.
Example (Taking one element)
import { MutableList } from "effect"
const list = MutableList.make<string>()MutableList.appendAll(list, ["first", "second", "third"])
// Take elements one by oneconsole.log(MutableList.take(list)) // "first"console.log(list.length) // 2
console.log(MutableList.take(list)) // "second"console.log(MutableList.take(list)) // "third"console.log(list.length) // 0
// Take from empty listconsole.log(MutableList.take(list)) // Empty symbol
// Check for empty using the Empty symbolconst result = MutableList.take(list)if (result === MutableList.Empty) { console.log("List is empty")} else { console.log("Got element:", result)}
// Consumer patternfunction processNext<T>(queue: MutableList.MutableList<T>, processor: (item: T) => void): boolean { const item = MutableList.take(queue) if (item !== MutableList.Empty) { processor(item) return true } return false}Signature
declare const take: <A>(self: MutableList<A>) => Empty | ASince v4.0.0
takeAll
Section titled “takeAll”Takes all elements from the MutableList and returns them as an array. The list becomes empty after this operation. This is equivalent to takeN(list, list.length).
Example (Draining all elements)
import { MutableList } from "effect"
const list = MutableList.make<string>()MutableList.appendAll(list, ["apple", "banana", "cherry"])
console.log(list.length) // 3
// Take all elementsconst allItems = MutableList.takeAll(list)console.log(allItems) // ["apple", "banana", "cherry"]console.log(list.length) // 0
// Useful for converting to array and clearingconst queue = MutableList.make<number>()MutableList.appendAll(queue, [1, 2, 3, 4, 5])
const snapshot = MutableList.takeAll(queue)console.log("Queue contents:", snapshot)console.log("Queue is now empty:", queue.length === 0)
// Drain pattern for processingfunction drainAndProcess<T>(list: MutableList.MutableList<T>, processor: (items: Array<T>) => void) { if (list.length > 0) { const items = MutableList.takeAll(list) processor(items) }}Signature
declare const takeAll: <A>(self: MutableList<A>) => Array<A>Since v4.0.0
Takes up to N elements from the beginning of the MutableList and returns them as an array. The taken elements are removed from the list. This operation is optimized for performance and includes zero-copy optimizations when possible.
Example (Taking batches)
import { MutableList } from "effect"
const list = MutableList.make<number>()MutableList.appendAll(list, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
console.log(list.length) // 10
// Take first 3 elementsconst first3 = MutableList.takeN(list, 3)console.log(first3) // [1, 2, 3]console.log(list.length) // 7
// Take more than availableconst remaining = MutableList.takeN(list, 20)console.log(remaining) // [4, 5, 6, 7, 8, 9, 10]console.log(list.length) // 0
// Take from empty listconst empty = MutableList.takeN(list, 5)console.log(empty) // []
// Batch processing patternconst queue = MutableList.make<string>()MutableList.appendAll(queue, ["task1", "task2", "task3", "task4", "task5"])
while (queue.length > 0) { const batch = MutableList.takeN(queue, 2) // Process 2 at a time console.log("Processing batch:", batch)}Signature
declare const takeN: <A>(self: MutableList<A>, n: number) => Array<A>Since v4.0.0
takeNVoid
Section titled “takeNVoid”Removes up to n elements from the beginning of the MutableList without
returning them.
When to use
Use to discard a bounded number of values from the head of a MutableList
when the removed values are not needed.
Details
If n is less than or equal to zero, or the list is empty, the list is left
unchanged. If n is greater than or equal to the current length, the list is
cleared.
See
takeNfor removing up tonvalues and returning them as an arrayclearfor removing every value from the list
Signature
declare const takeNVoid: <A>(self: MutableList<A>, n: number) => voidSince v4.0.0
toArray
Section titled “toArray”Copies all current elements of the MutableList into a new array without
modifying the list.
When to use
Use when you need a snapshot of all current elements while keeping the list unchanged.
See
takeAllfor converting all elements to an array and clearing the list
Signature
declare const toArray: <A>(self: MutableList<A>) => Array<A>Since v4.0.0
toArrayN
Section titled “toArrayN”Copies up to n elements from the beginning of the MutableList into a new
array without modifying the list.
When to use
Use when you need to inspect or snapshot a bounded prefix of the list without consuming it.
See
takeNfor removing up tonvalues and returning them as an array
Signature
declare const toArrayN: <A>(self: MutableList<A>, n: number) => Array<A>Since v4.0.0
models
Section titled “models”MutableList (interface)
Section titled “MutableList (interface)”A mutable linked list data structure optimized for high-throughput operations. MutableList provides efficient append/prepend operations and is ideal for producer-consumer patterns, queues, and streaming scenarios.
Example (Creating and consuming a mutable list)
import { MutableList } from "effect"
// Create a mutable listconst list: MutableList.MutableList<number> = MutableList.make()
// Add elementsMutableList.append(list, 1)MutableList.append(list, 2)MutableList.prepend(list, 0)
// Access propertiesconsole.log(list.length) // 3console.log(list.head?.array) // Contains elements from head bucketconsole.log(list.tail?.array) // Contains elements from tail bucket
// Take elementsconsole.log(MutableList.take(list)) // 0console.log(MutableList.take(list)) // 1console.log(MutableList.take(list)) // 2Signature
export interface MutableList<in out A> { head: MutableList.Bucket<A> | undefined tail: MutableList.Bucket<A> | undefined length: number}Since v2.0.0
mutations
Section titled “mutations”append
Section titled “append”Appends an element to the end of the MutableList. This operation is optimized for high-frequency usage.
Example (Appending elements)
import { MutableList } from "effect"
const list = MutableList.make<number>()
// Append elements one by oneMutableList.append(list, 1)MutableList.append(list, 2)MutableList.append(list, 3)
console.log(list.length) // 3
// Elements are taken from head (FIFO)console.log(MutableList.take(list)) // 1console.log(MutableList.take(list)) // 2console.log(MutableList.take(list)) // 3
// High-throughput usagefor (let i = 0; i < 10000; i++) { MutableList.append(list, i)}Signature
declare const append: <A>(self: MutableList<A>, message: A) => voidSince v2.0.0
appendAll
Section titled “appendAll”Appends all elements from an iterable to the end of the MutableList. Returns the number of elements added.
Example (Appending multiple elements)
import { MutableList } from "effect"
const list = MutableList.make<number>()MutableList.append(list, 1)MutableList.append(list, 2)
// Append multiple elementsconst added = MutableList.appendAll(list, [3, 4, 5])console.log(added) // 3console.log(list.length) // 5
// Elements maintain order: [1, 2, 3, 4, 5]console.log(MutableList.takeAll(list)) // [1, 2, 3, 4, 5]
// Works with any iterableconst newList = MutableList.make<string>()MutableList.appendAll(newList, new Set(["a", "b", "c"]))console.log(MutableList.takeAll(newList)) // ["a", "b", "c"]
// Useful for bulk loadingconst bulkList = MutableList.make<number>()const count = MutableList.appendAll( bulkList, Array.from({ length: 1000 }, (_, i) => i))console.log(count) // 1000Signature
declare const appendAll: <A>(self: MutableList<A>, messages: Iterable<A>) => numberSince v4.0.0
appendAllUnsafe
Section titled “appendAllUnsafe”Appends all elements from a ReadonlyArray to the end of the MutableList. This is an optimized version that can reuse the array when mutable=true. Returns the number of elements added.
When to use
Use when appending a trusted array directly is worth the optimized path and you control whether the input may be reused.
Gotchas
When mutable=true, the input array may be modified internally. Only use mutable=true when you control the array lifecycle.
Example (Appending arrays with optional mutation)
import { MutableList } from "effect"
const list = MutableList.make<number>()MutableList.append(list, 1)
// Safe usage (default mutable=false)const items = [2, 3, 4]const added = MutableList.appendAllUnsafe(list, items)console.log(added) // 3console.log(items) // [2, 3, 4] - unchanged
// Unsafe but efficient usage (mutable=true)const mutableItems = [5, 6, 7]MutableList.appendAllUnsafe(list, mutableItems, true)// mutableItems may be modified internally for efficiency
console.log(MutableList.takeAll(list)) // [1, 2, 3, 4, 5, 6, 7]
// High-performance bulk operationsconst bigArray = new Array(10000).fill(0).map((_, i) => i)MutableList.appendAllUnsafe(list, bigArray, true) // Very efficientSignature
declare const appendAllUnsafe: <A>(self: MutableList<A>, messages: ReadonlyArray<A>, mutable?: boolean) => numberSince v4.0.0
Removes all elements from the MutableList, resetting it to an empty state. This operation is highly optimized and releases all internal memory.
Example (Clearing a mutable list)
import { MutableList } from "effect"
const list = MutableList.make<number>()MutableList.appendAll(list, [1, 2, 3, 4, 5])
console.log(list.length) // 5
// Clear all elementsMutableList.clear(list)
console.log(list.length) // 0console.log(MutableList.take(list)) // Empty
// Can still use the list after clearingMutableList.append(list, 42)console.log(list.length) // 1
// Useful for resetting queues or buffersfunction resetBuffer<T>(buffer: MutableList.MutableList<T>) { MutableList.clear(buffer) console.log("Buffer cleared and ready for reuse")}Signature
declare const clear: <A>(self: MutableList<A>) => voidSince v4.0.0
filter
Section titled “filter”Filters the MutableList in place, keeping only elements that satisfy the predicate. This operation modifies the list and rebuilds its internal structure for efficiency.
Example (Filtering in place)
import { MutableList } from "effect"
const list = MutableList.make<number>()MutableList.appendAll(list, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
console.log(list.length) // 10
// Keep only even numbersMutableList.filter(list, (n) => n % 2 === 0)
console.log(MutableList.takeAll(list)) // [2, 4, 6, 8, 10]
// Filter with indexconst indexed = MutableList.make<string>()MutableList.appendAll(indexed, ["a", "b", "c", "d", "e"])
// Keep elements at even indicesMutableList.filter(indexed, (value, index) => index % 2 === 0)console.log(MutableList.takeAll(indexed)) // ["a", "c", "e"]
// Real-world example: filtering a log queueconst logs = MutableList.make<{ level: string; message: string }>()MutableList.appendAll(logs, [ { level: "INFO", message: "App started" }, { level: "ERROR", message: "Connection failed" }, { level: "DEBUG", message: "Cache hit" }, { level: "ERROR", message: "Timeout" }])
// Keep only errorsMutableList.filter(logs, (log) => log.level === "ERROR")console.log(MutableList.takeAll(logs).map((log) => log.message)) // ["Connection failed", "Timeout"]Signature
declare const filter: <A>(self: MutableList<A>, f: (value: A, i: number) => boolean) => voidSince v4.0.0
prepend
Section titled “prepend”Prepends an element to the beginning of the MutableList. This operation is optimized for high-frequency usage.
Example (Prepending elements)
import { MutableList } from "effect"
const list = MutableList.make<string>()
// Prepend elements (they'll be at the front)MutableList.prepend(list, "third")MutableList.prepend(list, "second")MutableList.prepend(list, "first")
console.log(list.length) // 3
// Elements taken from head (most recently prepended first)console.log(MutableList.take(list)) // "first"console.log(MutableList.take(list)) // "second"console.log(MutableList.take(list)) // "third"
// Use case: priority items or stack-like behaviorMutableList.append(list, "normal")MutableList.prepend(list, "priority") // This will be taken firstconsole.log(MutableList.take(list)) // "priority"Signature
declare const prepend: <A>(self: MutableList<A>, message: A) => voidSince v2.0.0
prependAll
Section titled “prependAll”Prepends all elements from an iterable to the beginning of the MutableList. The elements are added in order, so the first element in the iterable becomes the new head of the list.
Example (Prepending multiple elements)
import { MutableList } from "effect"
const list = MutableList.make<number>()MutableList.append(list, 4)MutableList.append(list, 5)
// Prepend multiple elementsMutableList.prependAll(list, [1, 2, 3])
console.log(list.length) // 5
// Elements are taken in order: [1, 2, 3, 4, 5]console.log(MutableList.takeAll(list)) // [1, 2, 3, 4, 5]
// Works with any iterableconst newList = MutableList.make<string>()MutableList.prependAll(newList, "hello") // Prepends each characterconsole.log(MutableList.takeAll(newList)) // ["h", "e", "l", "l", "o"]Signature
declare const prependAll: <A>(self: MutableList<A>, messages: Iterable<A>) => voidSince v4.0.0
prependAllUnsafe
Section titled “prependAllUnsafe”Prepends all elements from a ReadonlyArray to the beginning of the MutableList. This is an optimized version that can reuse the array when mutable=true.
When to use
Use when prepending a trusted array directly is worth the optimized path and you control whether the input may be reused.
Gotchas
When mutable=true, the input array may be modified internally. Only use mutable=true when you control the array lifecycle.
Example (Prepending arrays with optional mutation)
import { MutableList } from "effect"
const list = MutableList.make<number>()MutableList.append(list, 4)
// Safe usage (default mutable=false)const items = [1, 2, 3]MutableList.prependAllUnsafe(list, items)console.log(items) // [1, 2, 3] - unchanged
// Unsafe but efficient usage (mutable=true)const mutableItems = [10, 20, 30]MutableList.prependAllUnsafe(list, mutableItems, true)// mutableItems may be modified internally for efficiency
console.log(MutableList.takeAll(list)) // [10, 20, 30, 1, 2, 3, 4]Signature
declare const prependAllUnsafe: <A>(self: MutableList<A>, messages: ReadonlyArray<A>, mutable?: boolean) => voidSince v4.0.0
remove
Section titled “remove”Removes all occurrences of a value from the MutableList using JavaScript
strict equality semantics.
When to use
Use when in-place removal should use JavaScript identity/strict equality rather than Effect structural equality.
Details
The list is modified in place.
Gotchas
Values are compared with !==, so this does not use Effect structural
equality.
Example (Removing matching values)
import { MutableList } from "effect"
const list = MutableList.make<string>()MutableList.appendAll(list, ["apple", "banana", "apple", "cherry", "apple"])
console.log(list.length) // 5
// Remove all occurrences of "apple"MutableList.remove(list, "apple")
console.log(MutableList.takeAll(list)) // ["banana", "cherry"]
// Remove non-existent value (no effect)const colors = MutableList.make<string>()MutableList.appendAll(colors, ["red", "blue"])MutableList.remove(colors, "green")console.log(MutableList.takeAll(colors)) // ["red", "blue"]
// Real-world example: removing completed tasksconst tasks = MutableList.make<{ id: number; status: string }>()MutableList.appendAll(tasks, [ { id: 1, status: "pending" }, { id: 2, status: "completed" }, { id: 3, status: "pending" }, { id: 4, status: "completed" }])
// Remove completed tasks by filtering statusMutableList.filter(tasks, (task) => task.status !== "completed")console.log(MutableList.takeAll(tasks).map((task) => task.id)) // [1, 3]Signature
declare const remove: <A>(self: MutableList<A>, value: A) => voidSince v4.0.0
symbols
Section titled “symbols”Defines the unique symbol used to represent an empty result when taking elements from a MutableList.
This symbol is returned by take when the list is empty, allowing for safe type checking.
When to use
Use to detect that take returned no element before handling the result as a
list item.
Example (Checking for empty results)
import { MutableList } from "effect"
const list = MutableList.make<string>()
// Take from empty list returns Empty symbolconst result = MutableList.take(list)console.log(result === MutableList.Empty) // true
// Safe pattern for checking emptinessconst processNext = (queue: MutableList.MutableList<string>) => { const item = MutableList.take(queue) if (item === MutableList.Empty) { console.log("Queue is empty") return null } return item.toUpperCase()}
// Compare with other empty resultsMutableList.append(list, "hello")const next = MutableList.take(list)console.log(next !== MutableList.Empty) // true, got "hello"
const empty = MutableList.take(list)console.log(empty === MutableList.Empty) // true, list is emptySignature
declare const Empty: unique symbolSince v4.0.0
Empty (type alias)
Section titled “Empty (type alias)”The type of the Empty symbol, used for type checking when taking elements from a MutableList. This provides compile-time safety when checking for empty results.
Example (Handling empty results type-safely)
import { MutableList } from "effect"
const list = MutableList.make<number>()
// Type-safe handling of empty resultsconst takeAndDouble = (queue: MutableList.MutableList<number>): number | null => { const item: number | MutableList.Empty = MutableList.take(queue)
if (item === MutableList.Empty) { return null }
// TypeScript knows item is number here return item * 2}
console.log(takeAndDouble(list)) // null (empty list)
MutableList.append(list, 5)console.log(takeAndDouble(list)) // 10
// Type guard functionconst isEmpty = (result: number | MutableList.Empty): result is MutableList.Empty => { return result === MutableList.Empty}
const value = MutableList.take(list)if (isEmpty(value)) { console.log("List is empty")} else { console.log("Got value:", value)}Signature
type Empty = typeof EmptySince v4.0.0
MutableList (namespace)
Section titled “MutableList (namespace)”The MutableList namespace contains type definitions and utilities for working with mutable linked lists.
Example (Typing queue processors)
import { MutableList } from "effect"
// Type annotation using the namespaceconst processQueue = (queue: MutableList.MutableList<string>) => { while (queue.length > 0) { const item = MutableList.take(queue) if (item !== MutableList.Empty) { console.log("Processing:", item) } }}
// Using the namespace for type definitionsconst createProcessor = <T>(): { queue: MutableList.MutableList<T> add: (item: T) => void process: () => Array<T>} => { const queue = MutableList.make<T>() return { queue, add: (item) => MutableList.append(queue, item), process: () => MutableList.takeAll(queue) }}Since v2.0.0
Bucket (interface)
Section titled “Bucket (interface)”Storage node used by the exposed head and tail fields of a
MutableList.
Details
Most code should treat buckets as an implementation detail and use
MutableList operations such as append, prepend, and take instead
of constructing or mutating buckets directly.
Example (Inspecting buckets)
import { MutableList } from "effect"
const list = MutableList.make<number>()MutableList.append(list, 1)MutableList.append(list, 2)
// Access bucket information (for debugging or advanced usage)const inspectBucket = (bucket: MutableList.MutableList.Bucket<number> | undefined) => { if (bucket) { console.log("Bucket array:", bucket.array) console.log("Bucket offset:", bucket.offset) console.log("Bucket mutable:", bucket.mutable) console.log("Has next bucket:", bucket.next !== undefined) }}
inspectBucket(list.head)inspectBucket(list.tail)Signature
export interface Bucket<A> { readonly array: Array<A> mutable: boolean offset: number next: Bucket<A> | undefined}Since v4.0.0