MutableHashSet
MutableHashSet
A mutable MutableHashSet provides a collection of unique values with
efficient lookup, insertion and removal. Unlike its immutable sibling
:HashSet, a MutableHashSet can be modified in-place;
operations like add, remove, and clear directly modify the original set
rather than creating a new one. This mutability offers benefits like improved
performance in scenarios where you need to build or modify a set
incrementally.
What Problem Does It Solve?
MutableHashSet solves the problem of maintaining an unsorted collection
where each value appears exactly once, with fast operations for checking
membership and adding/removing values, in contexts where mutability is
preferred for performance or implementation simplicity.
When to Use
Use MutableHashSet when you need:
- A collection with no duplicate values
- Efficient membership testing (
O(1)average complexity) - In-place modifications for better performance
- A set that will be built or modified incrementally
- Local mutability in otherwise immutable code
Advanced Features
MutableHashSet provides operations for:
- Adding and removing elements with direct mutation
- Checking for element existence
- Clearing all elements at once
- Converting to/from other collection types
Performance Characteristics
- Lookup operations (:MutableHashSet.has):
O(1)average time complexity - Insertion operations (:MutableHashSet.add):
O(1)average time complexity - Removal operations (:MutableHashSet.remove):
O(1)average time complexity - Iteration:
O(n)where n is the size of the set
The MutableHashSet data structure implements the following traits:
- Iterable: allows iterating over the values in the set
- Pipeable: allows chaining operations with the pipe operator
- Inspectable: allows inspecting the contents of the set
Operations Reference
| Category | Operation | Description | Complexity |
|---|---|---|---|
| constructors | :MutableHashSet.empty | Creates an empty MutableHashSet | O(1) |
| constructors | :MutableHashSet.fromIterable | Creates a set from an iterable | O(n) |
| constructors | :MutableHashSet.make | Creates a set from multiple values | O(n) |
| elements | :MutableHashSet.has | Checks if a value exists in the set | O(1) avg |
| elements | :MutableHashSet.add | Adds a value to the set | O(1) avg |
| elements | :MutableHashSet.remove | Removes a value from the set | O(1) avg |
| elements | :MutableHashSet.size | Gets the number of elements | O(1) |
| elements | :MutableHashSet.clear | Removes all values from the set | O(1) |
Notes
Mutability Considerations:
Unlike most data structures in the Effect ecosystem, MutableHashSet is
mutable. This means that operations like add, remove, and clear modify
the original set rather than creating a new one. This can lead to more
efficient code in some scenarios, but requires careful handling to avoid
unexpected side effects.
When to Choose MutableHashSet vs :HashSet:
- Use
MutableHashSetwhen you need to build or modify a set incrementally and performance is a priority - Use
HashSetwhen you want immutability guarantees and functional programming patterns - Consider using :HashSet's bounded mutation context (via
:HashSet.beginMutation, :HashSet.endMutation, and
:HashSet.mutate methods) when you need temporary mutability
within an otherwise immutable context - this approach might be sufficient
for many use cases without requiring a separate
MutableHashSet MutableHashSetis often useful for local operations where the mutability is contained and doesn't leak into the broader application
Constructors
Creates an empty mutable hash set.
This function initializes and returns an empty MutableHashSet instance,
which allows for efficient storage and manipulation of unique elements.
Time complexity: O(1)
See
- Other
MutableHashSetconstructors are :MutableHashSet.make :MutableHashSet.fromIterable
Signature
declare function empty<K = never>(): MutableHashSet<K>Example
import { MutableHashSet } from "effect"
type T = unknown // replace with your type
// in places where the type can't be inferred, replace with your typeconst set: MutableHashSet.MutableHashSet<T> = MutableHashSet.empty<T>()fromIterable
Creates a new MutableHashSet from an iterable collection of values.
Duplicate values are omitted.
Time complexity: O(n) where n is the number of elements in the iterable
Creating a MutableHashSet from an Array
Creating a MutableHashSet from a Set
Creating a MutableHashSet from a Generator
Creating a MutableHashSet from another :MutableHashSet
Creating a MutableHashSet from an :HashSet
Creating a MutableHashSet from other Effect's data structures like
Chunk
See
- Other
MutableHashSetconstructors are :MutableHashSet.empty :MutableHashSet.make
Signature
declare function fromIterable<K = never>(keys: Iterable<K>): MutableHashSet<K>Example
import { MutableHashSet } from "effect"
const array: Iterable<number> = [1, 2, 3, 4, 5, 1, 2, 3] // Array<T> is also Iterable<T>const mutableHashSet: MutableHashSet.MutableHashSet<number> = MutableHashSet.fromIterable(array)
console.log( // MutableHashSet.MutableHashSet<T> is also an Iterable<T> Array.from(mutableHashSet)) // Output: [1, 2, 3, 4, 5]Example
import { MutableHashSet, pipe } from "effect"
console.log( pipe( // Set<string> is an Iterable<string> new Set(["apple", "banana", "orange", "apple"]), // constructs MutableHashSet from an Iterable Set MutableHashSet.fromIterable, // since MutableHashSet it is itself an Iterable, we can pass it to other functions expecting an Iterable Array.from )) // Output: ["apple", "banana", "orange"]Example
import { MutableHashSet } from "effect"
// Generator functions return iterablesfunction* fibonacci(n: number): Generator<number, void, never> { let [a, b] = [0, 1] for (let i = 0; i < n; i++) { yield a ;[a, b] = [b, a + b] }}
// Create a MutableHashSet from the first 10 Fibonacci numbersconst fibonacciSet = MutableHashSet.fromIterable(fibonacci(10))
console.log(Array.from(fibonacciSet))// Outputs: [0, 1, 2, 3, 5, 8, 13, 21, 34] but in unsorted orderExample
import { MutableHashSet, pipe } from "effect"
console.log( pipe( MutableHashSet.make(1, 2, 3, 4), MutableHashSet.fromIterable, Array.from )) // Output: [1, 2, 3, 4]Example
import { HashSet, MutableHashSet, pipe } from "effect"
console.log( pipe( HashSet.make(1, 2, 3, 4), // it works also with its immutable HashSet sibling MutableHashSet.fromIterable, Array.from )) // Output: [1, 2, 3, 4]Example
import { Chunk, MutableHashSet, pipe } from "effect"
console.log( pipe( Chunk.make(1, 2, 3, 4), // Chunk is also an Iterable<T> MutableHashSet.fromIterable, Array.from )) // Outputs: [1, 2, 3, 4]Construct a new MutableHashSet from a variable number of values.
Time complexity: O(n) where n is the number of elements
See
- Other
MutableHashSetconstructors are :MutableHashSet.fromIterable :MutableHashSet.empty
Signature
declare function make<Keys extends readonly Array<unknown>>(...keys: Keys): MutableHashSet<Keys[number]>Example
import { Equal, Hash, MutableHashSet } from "effect"import assert from "node:assert/strict"
class Character implements Equal.Equal { readonly name: string readonly trait: string
constructor(name: string, trait: string) { this.name = name this.trait = trait }
// Define equality based on name, and trait [Equal.symbol](that: Equal.Equal): boolean { if (that instanceof Character) { return ( Equal.equals(this.name, that.name) && Equal.equals(this.trait, that.trait) ) } return false }
// Generate a hash code based on the sum of the character's name and trait [Hash.symbol](): number { return Hash.hash(this.name + this.trait) }
static readonly of = (name: string, trait: string): Character => { return new Character(name, trait) }}
const mutableCharacterHashSet = MutableHashSet.make( Character.of("Alice", "Curious"), Character.of("Alice", "Curious"), Character.of("White Rabbit", "Always late"), Character.of("Mad Hatter", "Tea enthusiast"))
assert.equal( MutableHashSet.has( mutableCharacterHashSet, Character.of("Alice", "Curious") ), true)assert.equal( MutableHashSet.has( mutableCharacterHashSet, Character.of("Fluffy", "Kind") ), false)Elements
Checks whether the MutableHashSet contains the given element, and
adds it if not.
Time complexity: O(1) average
Syntax
See
- Other
MutableHashSetelements are :MutableHashSet.remove :MutableHashSet.size :MutableHashSet.clear :MutableHashSet.has
Signature
declare const add: { <V>(key: V): (self: MutableHashSet<V>) => MutableHashSet<V>; <V>(self: MutableHashSet<V>, key: V): MutableHashSet<V>;}Example
import { MutableHashSet, pipe } from "effect"
// with data-last, a.k.a. pipeable APIpipe( MutableHashSet.empty(), MutableHashSet.add(0), MutableHashSet.add(0))
// or piped with the pipe functionMutableHashSet.empty().pipe(MutableHashSet.add(0))
// or with data-first APIMutableHashSet.add(MutableHashSet.empty(), 0)Removes all values from the MutableHashSet.
This function operates by delegating the clearing action to the underlying
key map associated with the given MutableHashSet. It ensures that the hash
set becomes empty while maintaining its existence and structure.
See
- Other
MutableHashSetelements are :MutableHashSet.add :MutableHashSet.has :MutableHashSet.remove :MutableHashSet.size
Signature
declare function clear<V>(self: MutableHashSet<V>): MutableHashSet<V>Example
import { MutableHashSet, pipe } from "effect"import assert from "node:assert/strict"
assert.deepStrictEqual( pipe( MutableHashSet.make(1, 2, 3, 4), MutableHashSet.clear, MutableHashSet.size ), 0)Checks if the specified value exists in the MutableHashSet.
Time complexity: O(1) average
Syntax
See
- Other
MutableHashSetelements are :MutableHashSet.add :MutableHashSet.remove :MutableHashSet.size :MutableHashSet.clear
Signature
declare const has: { <V>(key: V): (self: MutableHashSet<V>) => boolean; <V>(self: MutableHashSet<V>, key: V): boolean;}Example
import { MutableHashSet, pipe } from "effect"import assert from "node:assert/strict"
assert.equal( // with `data-last`, a.k.a. `pipeable` API pipe(MutableHashSet.make(0, 1, 2), MutableHashSet.has(3)), false)
assert.equal( // or piped with the pipe function MutableHashSet.make(0, 1, 2).pipe(MutableHashSet.has(3)), false)
assert.equal( // or with `data-first` API MutableHashSet.has(MutableHashSet.make(0, 1, 2), 3), false)Removes a value from the MutableHashSet.
Time complexity: O(1) average
Syntax
See
- Other
MutableHashSetelements are :MutableHashSet.add :MutableHashSet.has :MutableHashSet.size :MutableHashSet.clear
Signature
declare const remove: { <V>(key: V): (self: MutableHashSet<V>) => MutableHashSet<V>; <V>(self: MutableHashSet<V>, key: V): MutableHashSet<V>;}Example
import { MutableHashSet, pipe } from "effect"import assert from "node:assert/strict"
assert.equal( // with `data-last`, a.k.a. `pipeable` API pipe( MutableHashSet.make(0, 1, 2), MutableHashSet.remove(0), MutableHashSet.has(0) ), false)
assert.equal( // or piped with the pipe function MutableHashSet.make(0, 1, 2).pipe( MutableHashSet.remove(0), MutableHashSet.has(0) ), false)
assert.equal( // or with `data-first` API MutableHashSet.remove(MutableHashSet.make(0, 1, 2), 0).pipe( MutableHashSet.has(0) ), false)Calculates the number of values in the HashSet.
Time complexity: O(1)
See
- Other
MutableHashSetelements are :MutableHashSet.add :MutableHashSet.has :MutableHashSet.remove :MutableHashSet.clear
Signature
declare function size<V>(self: MutableHashSet<V>): numberExample
import { MutableHashSet } from "effect"import assert from "node:assert/strict"
assert.equal(MutableHashSet.size(MutableHashSet.empty()), 0)
assert.equal( MutableHashSet.size(MutableHashSet.make(1, 2, 2, 3, 4, 3)), 4)Models
MutableHashSet interface
Signature
interface MutableHashSet<out V> extends Iterable<V>, Pipeable, Inspectable { readonly [TypeId]: typeof TypeId;}