Fact-checked by Grok 2 weeks ago

Immutable object

An immutable object is an object in object-oriented and whose internal state cannot be modified after it is fully constructed, ensuring that any apparent changes result in the creation of a new object rather than altering the original. This property distinguishes immutable objects from mutable ones, which allow in-place modifications to their data or attributes. Immutable objects provide significant benefits in , particularly in multithreaded environments, where they prevent and conditions by eliminating shared mutable state. They also enhance code predictability and maintainability, as developers can reason about program behavior without tracking potential side effects from modifications, a central to paradigms. Additionally, immutability can improve performance through optimizations like memory sharing and reduced synchronization overhead, as seen in the design of immutable strings in languages like . Common examples of immutable objects appear across programming languages. In , the String class is inherently immutable, supporting and efficient for duplicate values. Python's built-in types, including integers, floating-point numbers, strings, and tuples, are immutable, promoting safer data handling in sequences and promoting functional-style operations. Similarly, .NET provides immutable collections like ImmutableList, which use persistent data structures to enable efficient updates while preserving original instances.

Fundamentals

Definition and Basic Principles

An immutable object is a data structure whose state cannot be modified after it is created; any operation that purports to alter it instead produces a new object with the updated state. This principle contrasts with mutable objects, where internal fields or elements can be directly changed in place. Immutability is a foundational concept in computer science, particularly in paradigms that emphasize predictability and safety in data handling. The concept of immutable objects gained prominence in the late 1950s and early 1960s through the development of functional programming languages, notably Lisp, created by John McCarthy. In his seminal 1960 paper, McCarthy introduced symbolic expressions (S-expressions) in Lisp—atomic symbols or ordered pairs—manipulated via functional composition and recursion without side effects in the presented model, laying groundwork for immutability in programming languages. However, later Lisp implementations introduced mechanisms for mutating list structures, such as rplaca and rplacd, though the functional paradigm encouraged immutability.) This approach formalized the use of recursion without mutation in the theoretical design, enabling computations on shared substructures. To illustrate, consider pseudocode for an immutable integer and a mutable list: Immutable Integer Example:
let x = 5  // Creates immutable integer object
let y = x + 3  // Creates new immutable integer 8; x remains 5
Mutable List Example (for contrast in principle):
let lst = [1, 2, 3]  // Creates mutable list
lst.append(4)  // Modifies lst in place to [1, 2, 3, 4]
In the immutable case, "updates" involve reassignment to new objects, preserving the original. This design supports key principles like referential transparency, where an expression can be substituted with its evaluated value without altering the program's behavior, as ensured by the absence of side effects in pure functions.

Mutable vs. Immutable Objects

Mutable objects allow in-place modifications to their internal , typically through that directly alter fields or elements, which can introduce side effects that propagate through the program. For instance, a like setValue() on a mutable object updates its immediately, enabling efficient reuse but risking unintended changes if the object is accessed via multiple references. In contrast, immutable objects prohibit any post-creation modifications; operations that appear to change the object instead return a new instance with the updated , preserving the original object's and avoiding side effects. The primary advantage of immutability lies in reducing from unintended alterations, as the object's remain constant, facilitating easier code reasoning and verification of program behavior. This predictability enhances overall program correctness by minimizing issues like race conditions in concurrent environments, where shared mutable could otherwise lead to inconsistencies. Immutable designs also promote safer sharing of objects across components, as there is no possibility of external modifications corrupting the data. Mutability, while offering simplicity for frequent updates without allocation overhead, carries drawbacks such as increased susceptibility to errors, where changes via one reference unexpectedly affect others pointing to the same object. These errors can complicate and maintenance, as the non-local effects of modifications make it harder to flow and ensure reliability. To illustrate the differences, consider a scenario involving collection updates: with a mutable , appending an element modifies the existing structure directly, potentially altering its length and contents in place with minimal allocation but exposing it to side-effect risks if aliased. In an immutable , the same operation concatenates to create an entirely new list, leaving the original intact, which avoids aliasing issues but may incur higher memory usage from repeated object creation unless optimized. The table below compares key implications:
AspectMutable ObjectsImmutable Objects
State ModificationIn-place changes (e.g., via append() or set())New object creation for updates
Side EffectsHigh risk; modifications affect all referencesNone; originals remain unchanged
Memory EfficiencyLower overhead for repeated updates (reuse structure)Higher due to copies, but enables and optimizations like interning
Error PronenessProne to and unintended mods, increasing bugsReduced bugs; simplifies reasoning and testing
Aliasing concerns with mutable objects are particularly pronounced, as multiple can lead to subtle errors that immutability inherently mitigates by design.

Core Concepts

Immutability in Variables and References

Immutable variables bind to a value that cannot be rebound or altered after initialization, enforcing a fixed between the variable name and its . In languages like , the final keyword declares such variables, preventing reassignment while allowing mutation of mutable objects they reference unless further restrictions are applied. This mechanism promotes predictable behavior by isolating changes, though it does not inherently guarantee object-level immutability. Similarly, in , immutability is the default for variable bindings, with explicit mut annotations required for modification, leveraging rules to prevent during mutable access. References to immutable objects allow multiple variables or pointers to point to the same unchanging entity in memory, enabling efficient sharing without risk of unintended modifications through any reference. Reassigning such a reference creates a new binding to a different object, leaving the original immutable object intact and unaffected. For instance, in , variables serve as references to immutable objects like strings or tuples; assignment merely updates the reference without copying the object, as the value cannot be altered post-creation. This approach contrasts with mutable references, where changes propagate across all aliases, but for immutable cases, it ensures . In the Javari extension to , type annotations distinguish immutable references that prohibit modification of the object's transitive state, supporting safe sharing in object-oriented contexts. Immutable objects preserve a consistent object , where is determined by content rather than , and codes remain stable throughout the object's lifetime since no changes occur. In , the equals method for immutable classes like String compares values, and the corresponding hashCode method yields the same result for equal instances, adhering to the that equal objects must share hash codes to support reliable use in hash-based collections. This content-based identity avoids issues arising from mutable , ensuring that an object's hash code does not vary if its value does not. enforces similar consistency for hashable immutable types, requiring __hash__ implementations to be invariant with respect to __eq__, preventing errors in sets or dictionaries. In heap-based memory models, immutable objects are allocated once in the and referenced by multiple , forming a directed reference graph where nodes represent objects and edges denote . This structure facilitates garbage collection by identifying reachable immutable objects without mutation concerns, as seen in systems like the or Python's interpreter. The following simple diagram illustrates a reference graph for immutable objects:
[Variable](/page/Variable) A ───┐
              ├── Immutable Object X ([heap](/page/Heap))
[Variable](/page/Variable) B ───┘     │
                    ├── Field: Immutable Value Y
                    └── Field: [Reference](/page/Reference) to Immutable Object Z
[Variable](/page/Variable) C ──────────────────────┘ (also [references](/page/Reference) Z)
Here, reassigning Variable A to a new object creates a separate in the , without altering X or Z, promoting memory efficiency through shared immutable structures.

Strong vs. Weak Immutability

immutability enforces that an object cannot be modified through any access , with guarantees provided by the language's to prevent all forms of , including internal changes. This level of enforcement often relies on compile-time checks, such as const-correctness extended transitively across all reachable components or sealed classes that prohibit subclassing and ensure final fields remain unchanged. In practice, strong immutability supports pure functions by ensuring inputs and outputs are unaltered, enabling reliable reasoning about program behavior without side effects. Weak immutability, in contrast, permits internal mutations but exposes only immutable views to external code, typically through mechanisms like defensive copying in accessors or read-only references that do not guarantee global non-modifiability. For instance, a might return a shallow copy of an internal mutable structure, allowing the object's state to change behind the scenes while preventing direct external alterations. This approach balances flexibility with partial safety, often used where performance constraints make full immutability impractical. The distinction between strong and weak immutability has evolved alongside programming paradigms. Strong immutability emerged in the type systems of ML-family functional languages during the 1970s, where immutable values became the default to support and concurrency safety in systems like LCF's Meta Language (1973–1978). Weak immutability gained prominence in object-oriented languages like (introduced 1995), relying on conventions and patterns rather than strict type enforcement to achieve practical immutability in mutable environments.
CriterionStrong ImmutabilityWeak Immutability
Enforcement MechanismCompile-time type system guarantees (e.g., transitive const or sealed types); no mutable paths exist.Runtime or alias-specific restrictions (e.g., defensive copies or read-only views); mutations possible via other paths.
Use CasesPure functions, formal verification, and high-assurance concurrency where absolute non-modification is required.Performance-sensitive scenarios like caching or legacy integration, providing immutability illusions without full overhead.
Pseudocode Examplepseudocode<br>sealed class Point(val x: Int, val y: Int) // No subclassing, final fields<br> def distance(other: Point): Double = math.sqrt((x - other.x)^2 + (y - other.y)^2)<br>// Type system ensures Point instances never mutate<br>pseudocode<br>class Container(private var data: Array[Int])<br> def getData: Array[Int] = data.clone // Defensive copy<br> private def updateInternal(newData: Array[Int]): Unit = data = newData // Internal mutation allowed<br>// External views are immutable, but object can change internally<br>

Aliasing and Object Identity

Aliasing occurs when multiple variables or references point to the same underlying object in , creating multiple names for the same . In programming languages, this is common with objects, where assigning one reference to another (e.g., z = x) results in both variables sharing the object's without copying its contents. With mutable objects, introduces risks such as "mutation at a distance," where changes through one reference unexpectedly alter the object observed via another, leading to bugs that are difficult to trace. For instance, modifying a list via one alias can silently affect all aliases, causing inconsistent state. In concurrent environments, this exacerbates issues like race conditions, where unsynchronized access to shared mutable by multiple threads results in unpredictable outcomes. Immutability mitigates these problems by prohibiting modifications after creation, ensuring that aliased references always observe the same unchanging value without side effects or coordination needs. Immutable objects preserve through value-based , where comparison operators (e.g., ==) evaluate structural content rather than addresses or pointer , distinguishing them from mutable objects that often rely on reference . This approach avoids pitfalls of pointer-based comparisons, such as false inequalities for semantically equivalent but separately allocated objects. In languages with collection, safe of immutable objects enables compiler and runtime optimizations, including , where repeated computations yielding the same immutable value can be reused without recomputation. Interning serves as one such technique, where identical immutable values share a single representation to further enhance efficiency.

Implementation Techniques

Copy-on-Write Optimization

Copy-on-write (CoW) is a resource-management optimization technique that enables efficient sharing of mutable data structures across multiple references by deferring the actual copying of data until a write operation is required. In this approach, initially shared copies are marked as read-only, allowing multiple entities to access the same underlying data without immediate duplication costs; upon a modification attempt, the system creates a private writable copy for the modifying entity while leaving other references intact. This mechanism is foundational for implementing immutability in scenarios where read operations dominate, as it supports the creation of lightweight, immutable views of potentially mutable data without upfront full copies. The technique finds application in various domains, including operating systems and specialized data structures. In systems, CoW is employed during process forking to share the parent's pages between parent and child processes until a write occurs, avoiding the overhead of duplicating the entire immediately. Similarly, in data structures like ropes—binary trees representing concatenated strings—CoW allows efficient and operations by sharing immutable subtrees; modifications copy only the affected path in the tree, typically O(log n) nodes, preserving immutability for unchanged parts. A typical for CoW in a simple -like structure involves to track sharing. Consider for updating an element in a shared :
function update([array](/page/Array)_ref, index, new_value):
    if [array](/page/Array)_ref.reference_count > 1:
        new_[array](/page/Array) = copy([array](/page/Array)_ref.[data](/page/Data))
        [array](/page/Array)_ref.[data](/page/Data) = new_[array](/page/Array)
        [array](/page/Array)_ref.reference_count = 1  // Detach from shared
    [array](/page/Array)_ref.[data](/page/Data)[index] = new_value
Here, the reference count determines if sharing exists; if shared, a deep copy is made before , ensuring . This outline mirrors implementations in systems supporting CoW for inheritance. Historically, CoW emerged in the context of Unix process creation with the fork() system call, introduced in the early 1970s, but full CoW optimizations for memory management were developed in the 1980s to address performance bottlenecks in virtual memory systems. These ideas were later extended to user-level programming, notably in C++ through reference-counted smart pointers like those in the Boost library (introduced around 2001), which facilitated CoW idioms for custom immutable types by enabling shared ownership with lazy copying on mutation. For immutability, CoW provides significant benefits by allowing inexpensive creation of immutable snapshots or views from mutable bases, as reads can leverage shared structures without allocation, while writes trigger targeted copies to maintain —ideal for scenarios like versioned data or functional updates where most operations are non-modifying. In concurrent environments, this yields gains by minimizing and copy overhead in read-intensive workloads.

Interning and Shared Structures

Interning is a optimization technique applied to immutable objects, where a maintains a centralized of unique instances for identical values, ensuring that subsequent creations reuse existing objects rather than allocating new ones. This process typically employs a for efficient lookups: upon creating an immutable object, such as a , the computes its and checks the for a matching entry based on ; if found, the existing reference is returned, otherwise the new object is inserted into the . The requirement for immutability is critical, as it prevents any shared instance from being modified, which could affect all aliases unexpectedly. In practice, interning is implemented differently across languages but follows this core mechanism. For instance, in , the String class automatically interns all string literals into a private, fixed-size pool during class loading, while the explicit intern() method allows runtime interning of other strings by returning a canonical representation from the pool. Similarly, Python's sys.intern() function manually interns strings into a global dictionary-like table to accelerate operations like dictionary key lookups, where equal keys must resolve to the same object for hashing consistency. These implementations use hash-based structures to balance lookup speed and memory usage, with pools often garbage-collectable in modern virtual machines to reclaim unused entries. The origins of interning trace back to , introduced around 1958 for handling symbols as unique atomic entities. In early systems, symbols were stored with a single association list per name, ensuring uniqueness via direct address comparison with the predicate, which laid the foundation for efficient symbolic computation in applications. This approach has since become common in modern virtual machines for primitives like small integers and strings, promoting shared structures without the risks associated with mutability. By facilitating object reuse, interning significantly reduces memory consumption in scenarios with high duplication, such as parsing repeated identifiers or constants, and accelerates testing through comparison rather than content evaluation. For example, in , interned strings allow the == operator to perform pointer checks instantaneously, bypassing the more expensive equals() method. This efficiency extends the benefits of to immutable objects, where multiple safely point to the same instance, enhancing overall program without introducing concurrency issues.

Persistent Data Structures

Persistent data structures are immutable data structures designed to support non-destructive updates, where modifications produce new versions of the structure while preserving all previous versions through structural sharing of unchanged components. This approach ensures that updates do not alter existing data, maintaining immutability while achieving efficiency comparable to mutable counterparts in many cases. The core mechanism involves creating new nodes only for the affected parts, allowing multiple versions to coexist by referencing shared substructures. A fundamental concept in persistent data structures is versioning via root pointers: each update operation returns a new root that points to the modified structure, while the original root remains valid and unchanged, enabling access to historical states without additional storage for unmodified elements. This versioning supports applications requiring audit trails or reversible computations, such as systems or environments. Immutability is enforced because nodes are never modified in place; instead, new paths or nodes are constructed as needed. One foundational technique for achieving persistence is path copying, commonly applied to tree-based structures like s. In path copying, an update copies only the path from the to the modified , sharing the unchanged subtrees with the original version. For example, inserting a key into a involves creating new nodes along the insertion path while reusing existing left and right subtrees where applicable. To illustrate structural sharing in a update, consider a simple before and after inserting a new value. The original tree (version 1) has node A with left child B and right child C. Inserting into the left subtree of B creates a new path: a new A' points to a new B' (with the updated left child), but B's right subtree and C remain shared.
Version 1 (Original):
      A
     / \
    B   C
   / \
  D   E

Version 2 (After insert under B's left):
      A'
     / \
    B'  C  (shared)
   / \
  D'  E  (shared)
 / 
F
Here, nodes C, E, and D (if unchanged) are shared between versions, minimizing space overhead to O(log n) for balanced . This technique, a building block extending principles, ensures O(log n) time and space per update. Persistent lists can be implemented using cells, as in , where each cons operation creates a new pointing to the existing , naturally without . This results in a persistent singly-linked list where appending or prepending yields a new list sharing all but the new head . For more complex sequences, finger provide a versatile persistent supporting efficient access and modification at both ends in amortized O(1) time, using a spine of nodes with measured subtrees to balance operations. Finger generalize deques and sequences through monoidal annotations, enabling applications like priority queues or random-access lists. The development of persistent data structures originated in paradigms, with significant advancements in the late 20th century. Chris Okasaki's seminal work, "Purely Functional Data Structures" (1998), systematized techniques for amortized and worst-case efficient persistence, influencing implementations in languages like . Earlier foundations trace to papers on making mutable structures persistent, such as those by Sleator and Tarjan in 1985.

Benefits and Trade-offs

Thread Safety and Concurrency

Immutable objects inherently provide in concurrent environments because their state cannot be altered after creation, eliminating the possibility of race conditions during simultaneous reads by multiple threads. Without mutable shared state, threads can access and share these objects freely without requiring synchronization primitives such as locks or mutexes, which would otherwise introduce contention and potential deadlocks. This property stems from the absence of interfering writes, allowing developers to focus on logic rather than coordinating access. In practice, passing immutable data structures between s in concurrent programs prevents race conditions that plague mutable alternatives. For instance, a producing an immutable list can safely share it with consumer s for , as modifications would require creating new objects rather than altering the original. This contrasts sharply with mutable objects, where synchronized blocks or operations are necessary to protect shared state, often leading to performance bottlenecks from lock acquisition and release. By design, immutability shifts the burden from to compile-time or structural guarantees. An advanced application appears in the , where Erlang—developed in the —relies on immutable messages for to ensure . Each (lightweight process) maintains isolated state and exchanges only unmodifiable messages via asynchronous passing, avoiding any shared mutable data and thus eliminating the need for locks across distributed systems. This isolation enables fault-tolerant concurrency, with processes handling messages sequentially in their private context. Immutability further enables lock-free data structures, such as persistent or queues, where updates produce new versions without modifying existing ones, allowing concurrent readers to operate without barriers. This eliminates costs entirely for read-heavy workloads, facilitating scalable parallelism in high-throughput applications. In multi-threaded contexts, it also addresses concerns by guaranteeing that multiple to the same object reflect consistent, unchanging values.

Performance Implications

Immutable objects, by design, cannot be modified after creation, which introduces specific performance costs primarily related to memory allocation and garbage collection. Every "update" operation requires creating a new object, leading to increased allocation pressure on the . In languages with automatic like , this can result in more frequent garbage collection pauses, as the runtime must reclaim unused objects more often. For instance, naive in loops—where strings are immutable—exhibits O(n²), as each concatenation copies the entire previous into a new object, accumulating redundant copies. To mitigate these costs, developers employ techniques such as builder patterns or specialized mutable builders that defer immutability until the final object is constructed. In , for example, the StringBuilder class allows efficient in-place modifications during construction, achieving linear O(n) time for building strings, after which the immutable is created only once. Similarly, efficient constructors that initialize immutable objects in a single allocation step can reduce overhead compared to incremental updates. These approaches balance the safety of immutability with the efficiency of mutability during transient phases. On the benefits side, immutable objects enhance efficiency because their contents never change, avoiding cache invalidations that occur with mutable data. This predictability allows data to remain resident in CPU caches longer, improving access times for repeated reads. Additionally, compilers can apply aggressive optimizations to immutable code, such as , where expressions involving immutable values are evaluated at rather than , reducing execution overhead. In the JVM, immutability enables further optimizations like eliding unnecessary checks for final fields. Empirical studies highlight the trade-offs, showing typical overheads in object-oriented languages but potential gains in functional paradigms through shared structures. Techniques like further reduce costs by sharing unmodified portions of data structures across versions.

Enforcing and Violating Immutability

Enforcing immutability in programming languages often relies on language features and design patterns that prevent state changes after object creation. In languages like , declaring fields as final ensures they cannot be reassigned once initialized, providing a foundational mechanism for immutability by guaranteeing that the object's state remains constant throughout its lifetime. Private constructors further support this by restricting instantiation to controlled factory methods or builders, which can enforce validation and prevent direct access that might lead to mutable instances. Type systems can enhance enforcement through annotations; for instance, Project Lombok's @Value annotation automatically generates immutable classes with private final fields, getters, and no setters, simplifying the creation of thread-safe objects without . Despite these safeguards, immutability can be violated through various mechanisms, often intentionally for debugging or unintentionally due to oversight. Reflection APIs allow bypassing access modifiers, enabling modification of private final fields in supposedly immutable objects, which undermines the intended guarantees and can introduce subtle bugs. A common accidental violation occurs when an immutable class exposes mutable inner objects, such as returning a modifiable array or list from a getter method, allowing external code to alter the object's internal state indirectly. Unsafe casts, particularly in systems with weak type safety, can convert read-only references to mutable ones, leading to unauthorized modifications that violate the immutability contract. Detecting such violations requires static analysis tools that inspect code for potential breaches. SpotBugs, the successor to FindBugs, performs bytecode analysis to identify issues like exposure of internal representations or improper handling of final fields, helping developers catch immutability flaws early in the development cycle. These violations carry significant risks, including security vulnerabilities where assumed-immutable data is modified, potentially enabling or ; for example, the CWE-471 category documents cases in drivers and systems where altering immutable addresses leads to exploitable conditions.

Language-Specific Implementations

Java and JVM Languages

In , immutability is primarily enforced through the final keyword, which prevents reassignment of variables, fields, and parameters after initialization, and restricts subclassing of classes when applied to the class itself. This mechanism supports the creation of immutable classes by ensuring that instance fields cannot be modified post-construction, as seen in core types like . The class, introduced in JDK 1.0 in 1996, is a foundational immutable type whose instances cannot be altered after creation, promoting safe sharing across threads and reducing memory overhead through an interned string pool that reuses identical string literals via the intern() method. Introduced in Java 8 (2014), the concept of "effectively final" variables extends immutability to local variables used in lambdas and inner classes; these are variables that are never reassigned after initialization, even without explicit final declaration, allowing their capture in functional constructs without risking concurrent modification. Scala, a JVM language emphasizing functional programming, builds on Java's immutability with language-level features like val declarations, which create immutable values akin to Java's final fields but with stricter enforcement and no reassignment possible. Case classes in Scala automatically generate immutable accessor methods for constructor parameters (treated as val fields), along with structural equals, hashCode, and toString implementations, facilitating concise modeling of immutable data without boilerplate. Recent enhancements further streamline immutability. , previewed in Java 14 (2020) via JEP 359, provide a compact syntax for shallowly immutable data carriers with final components, automatically generated accessors, equals, hashCode, and toString, reducing verbosity for plain data classes. Project Valhalla, an ongoing effort, introduces preview value types (e.g., via JEP 401 in early-access builds from 2023–2025) as identity-less, immutable primitives that eliminate object overhead while supporting user-defined types, enhancing performance for numerical and data-oriented applications. To design immutable classes in , developers mark all fields as private final, provide a constructor for initialization, and avoid exposing mutable state; for instance, getters returning collections should use defensive copying or return unmodifiable views to prevent external modification.
java
public final class ImmutablePoint {
    private final int x;
    private final int y;

    public ImmutablePoint(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() { return x; }
    public int getY() { return y; }
}
When a must hold mutable collections, best practices recommend returning defensive copies in getters, such as Collections.unmodifiableList(new ArrayList<>(internalList)), to preserve internal immutability without sharing modifiable references. In , case classes inherently follow similar principles, with parameters as immutable vals and encouraging functional, non-mutating usage.
scala
case class Point(x: Int, y: Int)
val p = Point(1, 2) // Immutable instance; no setters

Python and Dynamic Languages

In Python, several built-in types are inherently immutable, including integers, strings, and tuples, which cannot be modified after creation to ensure predictable behavior and enable optimizations like hashing. The frozenset type provides an immutable alternative to the mutable set, allowing hashable collections of unique elements that remain unchanged once constructed. For creating lightweight, immutable records with named fields, Python offers collections.namedtuple since version 2.6, which subclasses tuples to provide attribute access while preserving immutability. Additionally, since Python 3.7, the dataclasses module introduces the @dataclass(frozen=True) decorator, which generates immutable classes by raising an error on attribute modification attempts, emulating true immutability for user-defined data structures. However, Python's dynamic typing introduces challenges to strict immutability; while the structure of immutable types like tuples cannot change, they can reference mutable objects, allowing indirect modifications that alter the effective value of the container. For instance, a tuple containing a list permits changes to the list's contents, highlighting the limitations of shallow immutability in dynamic environments. Recent updates in Python 3.12 enhance typing support for expressing immutability through improved generic type parameters and type aliases, enabling static type checkers to better enforce immutable hints via constructs like typing.Final. In , a dynamically typed language, immutability is supported through the const keyword introduced in ECMAScript 6 (ES6) in 2015, which prevents reassignment of variables but does not protect against mutation of object properties. The Object.freeze() method provides shallow immutability by preventing additions, deletions, or reconfigurations of an object's properties, though nested objects remain mutable. For deeper, persistent immutability, libraries like Immutable.js offer specialized data structures such as List, Map, and Set, which create new instances on updates rather than modifying existing ones, facilitating efficient handling of complex state in applications. The Records and Tuples proposal, previously at Stage 2, was withdrawn in April 2025 due to performance and implementation challenges in engines and thus not included in ES2025, though its concepts continue to influence discussions on built-in immutability. These features underscore the trade-offs in dynamic languages, where flexibility often requires explicit tools or libraries to achieve robust immutability without compromising .

C++ and Systems Languages

In C++, immutability is enforced primarily through the const type qualifier, introduced in the C++98 standard, which declares objects or references that cannot be modified after initialization. The const qualifier can apply to variables, pointers, and references; for instance, a const int prevents reassignment, while a const member function promises not to alter the object's non-mutable state, enabling safe const-correctness in class designs. This manual approach requires programmers to explicitly propagate const through interfaces to avoid compilation errors when attempting modifications. C++11 extended compile-time immutability with the constexpr specifier, allowing variables, functions, and objects to be evaluated at , ensuring their values are constant and immutable during execution. For example, a constexpr function can compute results used in array sizes or template parameters, promoting optimization and preventing runtime changes. In C++17, std::string_view introduced a lightweight, non-owning view over a contiguous character , providing an immutable reference without copying the underlying data, which is particularly useful for passing strings to functions without . In systems languages like C#, the readonly keyword declares fields that can only be assigned during declaration or in a constructor, enforcing immutability at the instance level after initialization. C# 10 introduced record structs, value types that support immutability by default when declared as readonly record struct, combining structural equality with positional syntax for concise, thread-safe . The System.Collections.Immutable provides specialized collections like ImmutableList<T> and ImmutableDictionary<TKey, TValue>, which return new instances on modification operations, preserving the original data's immutability without shared mutable state. Developers in these languages often manually enforce immutability using smart pointers, such as C++'s std::shared_ptr, which enables shared ownership and can implement (CoW) semantics by delaying copies until mutation, though this requires careful design to avoid pointer where multiple references unexpectedly modify shared data. Recent updates include C++23's enhancements to modules, which improve const propagation in immediate functions via consteval upward propagation (P2564R2), strengthening compile-time guarantees. In C#, features from C# 8 onward, refined in the 2020s with record types, facilitate deconstruction and switching on immutable data for safer, more expressive code.
cpp
// Example: Immutable view in C++
std::string str = "hello";
std::string_view view = str;  // Non-owning, immutable reference
// view[0] = 'H';  // Compilation error
csharp
// Example: Immutable record struct in C# 10
readonly record struct Point(int X, int Y);
// Creates an immutable value type with value-based equality

Rust and Memory-Safe Languages

In Rust, a systems programming language designed with memory safety in mind, immutability is enforced by default through its ownership model, which tracks the lifetime and mutability of data at compile time. Variables declared with let are immutable, meaning their values cannot be changed after initialization, promoting safer code by preventing unintended modifications. To allow mutation, the mut keyword must be explicitly added, as in let mut x = 5;. Similarly, references created with & are immutable by default and cannot be used to modify the referenced data, while mutable references require &mut. This design choice ensures that data access is explicit and controlled, reducing bugs related to unexpected state changes. Central to Rust's immutability enforcement is the system, where each value has a single owner responsible for its , and the borrow checker—a part of the compiler—validates borrowing rules to prevent issues like data races or invalid memory access. The borrow checker enforces that data cannot be aliased (multiple references existing simultaneously) while being mutated, adhering to the principle that data should not be both aliased and mutated. For instance, multiple immutable borrows (&T) can coexist, but a mutable borrow (&mut T) requires exclusive access, and immutable borrows must outlive any mutable ones to avoid lifetime violations. This compile-time verification catches potential errors early, ensuring without a garbage collector. For duplicating data in a safe manner, provides the Copy and traits, introduced in the language's 1.0 stable release in 2015. The Copy trait enables implicit, bitwise copying for simple types like integers or tuples without allocation, but only for types that do not implement Drop to avoid resource leaks. More complex types implement for explicit deep copying via the clone() method, allowing controlled duplication while respecting rules. These s ensure that immutability is preserved during value transfer, as copies create independent instances without shared mutable state. Rust also supports interior mutability for scenarios where mutation is needed despite immutable outer references, using types like Rc<RefCell<T>> to enable shared and runtime-checked borrowing. Rc () provides multiple immutable pointers to the same data, while RefCell wraps the inner value and enforces borrowing rules dynamically via panics on violations, rather than at . This pattern is a controlled exception to strict immutability, useful for single-threaded code like mock objects in tests, but it introduces runtime overhead and potential panics if rules are breached. For example:
rust
use std::rc::Rc;
use std::cell::RefCell;

let data = Rc::new(RefCell::new(5));
*data.borrow_mut() += 1;  // Mutable access via RefCell
This allows mutation through immutable Rc references but maintains memory safety. The Rust 2024 edition introduces enhancements to pattern matching that improve handling of immutable references, making code more ergonomic without explicit ref or mut keywords in many cases. Under the new match ergonomics (RFC 3627), patterns can infer reference types from context, allowing & patterns to match against &mut targets seamlessly and reducing verbosity in immutable bindings. This update streamlines immutable data deconstruction in match expressions while preserving the borrow checker's guarantees. Rust's approach to immutability via and borrowing draws comparisons to memory-safe languages like Ada and , which also prioritize compile-time safety but differ in mechanisms. Ada's strong typing and lack of unrestricted pointers prevent many memory errors, similar to Rust's borrow checker, though Ada relies more on runtime checks for dynamic allocation. combines garbage collection with safe defaults, offering immutability through const and immutable qualifiers, but lacks Rust's fine-grained ownership for zero-cost abstractions. These languages share Rust's goal of eliminating common vulnerabilities like buffer overflows, with Rust emphasizing performance-critical systems.

Functional Languages (e.g., , )

In functional languages like and , immutability serves as a foundational principle that enables pure functions, , and efficient handling of data structures without side effects. , as specified in its 1998 language report, enforces immutability by default for all data bindings, meaning once a value is assigned to a name, it cannot be altered, which aligns with the language's emphasis on purity. Pure functions in produce outputs solely determined by their inputs, with no observable side effects such as mutation or I/O unless explicitly managed through monads. This design promotes reasoning about code as mathematical expressions, where the same inputs always yield identical results regardless of execution context. Haskell's strategy further leverages immutability by delaying computation until values are needed, allowing shared substructures across expressions through thunks to avoid redundant allocations and computations. , a hallmark of , relies on immutability to ensure that any expression can be replaced by its evaluated value without altering the program's meaning or behavior. For instance, folding over an immutable list, such as computing the sum with foldr (+) 0 [1,2,3], processes elements functionally without modifying the original structure, preserving transparency and enabling optimizations like fusion. Recent advancements in the (GHC) version 9.8, released in , include the Compact module, which optimizes garbage collection for long-lived immutable data structures by compacting them into contiguous regions, reducing fragmentation and improving performance for persistent structures. Scala builds on functional principles while running on the JVM, making immutable data structures central to its collections library, where types like Seq and Map default to immutable implementations that resist in-place modifications. The language favors val declarations for immutable bindings, which cannot be reassigned after initialization, over var for mutable ones, encouraging safer and more predictable code. This preference supports Scala's hybrid nature, as it interoperates seamlessly with Java's mutable objects—such as using Java collections within Scala code—but advises wrapping or converting them to immutable forms to maintain functional idioms. Scala 3, released in March 2021, enhances immutability support through native enums, which define sealed, immutable algebraic data types as case objects or classes, facilitating pattern matching and exhaustive checks without runtime mutability risks.

Other Languages (e.g., , Go)

Go lacks language-level immutability primitives, but effective immutability can be enforced for structs by using unexported (lowercase) fields, which prevent external packages from modifying them directly, combined with getter methods for read access. This approach aligns with Go's philosophy of explicit concurrency safety, where immutable values are safely passed over channels without modification risks during transmission, a feature available since Go's initial release in 2009. Other languages exhibit varying degrees of support for immutability. PHP introduced readonly properties in version 8.1 (released November 2021), allowing properties to be set only during object construction and preventing subsequent changes, with readonly classes in PHP 8.2 (2022) extending this to all properties by default for fully immutable objects. In Perl, the constant pragma declares compile-time constants as subroutines that return fixed scalar or list values, enforcing immutability by replacing the symbol with its value at compile time, a mechanism dating back to Perl 5. Racket supports immutable structs natively through its struct definition, where fields are unchangeable after creation unless explicitly declared mutable, promoting functional programming patterns with optimizations for immutable data. Swift emphasizes immutability via the let keyword for constants, which cannot be reassigned, and value types like structs that are copied on assignment rather than referenced, reducing shared mutable state; these features were refined in Swift 5 (March 2019) with improved copy-on-write semantics. Immutability has seen growing adoption in web development languages during the 2010s, particularly for reactive frameworks like (initially released in 2013), where immutable state updates enable efficient change detection and predictable UI rendering without direct mutations.

References

  1. [1]
    Immutable Objects - Essential Java Classes
    An object is considered immutable if its state cannot change after it is constructed. Maximum reliance on immutable objects is widely accepted as a sound ...
  2. [2]
    Immutable - Glossary - MDN Web Docs
    Jul 11, 2025 · An immutable value is one whose content cannot be changed without creating an entirely new value, in comparison with mutable values.
  3. [3]
    5. Data Structures — Python 3.14.0 documentation
    Tuples are immutable, and usually contain a heterogeneous sequence of elements that are accessed via unpacking (see later in this section) or indexing (or even ...5. Data Structures · 5.1. More On Lists · 5.3. Tuples And Sequences
  4. [4]
    .NET Framework - Immutable Collections | Microsoft Learn
    The fundamental benefit of immutability is that it makes it significantly easier to reason about how the code works, enabling you to quickly write correct and ...
  5. [5]
    F# Basics - An Introduction to Functional Programming for .NET ...
    In contrast, immutable variables introduce significantly less complexity. They lead to functional techniques like using functions as values and compositional ...
  6. [6]
    Design and History FAQ — Python 3.14.0 documentation
    There are several advantages. One is performance: knowing that a string is immutable means we can allocate space for it at creation time, and ...
  7. [7]
    String (Java Platform SE 8 ) - Oracle Help Center
    String buffers support mutable strings. Because String objects are immutable they can be shared. For example: String str = "abc";. is equivalent to: char ...Frames · Uses of Class java.lang.String · CharSequence · Pattern
  8. [8]
    Built-in Types — Python 3.14.0 documentation
    The principal built-in types are numerics, sequences, mappings, classes, instances and exceptions. Some collection classes are mutable.Built-In Types · Text Sequence Type -- Str · String Methods
  9. [9]
    Collections and Data Structures - .NET - Microsoft Learn
    Aug 12, 2022 · Enumerating an ImmutableList<T> using a foreach loop is efficient because ImmutableList<T> uses a binary tree to store its data instead of an ...<|control11|><|separator|>
  10. [10]
    Reading 9: Mutability & Immutability - MIT
    Other objects are mutable: they have methods that change the value of the object. String is an example of an immutable type.
  11. [11]
    [PDF] Recursive Functions of Symbolic Expressions and Their ...
    John McCarthy, Massachusetts Institute of Technology, Cambridge, Mass. ∗. April 1960. 1 Introduction. A programming system called LISP (for LISt Processor) ...Missing: immutability | Show results with:immutability
  12. [12]
    [PDF] Origins of Garbage Collection
    McCarthy insists that S-expression structures be immutable, allowing for copying by reference sharing. This optimization, as well as a future relax- ation on ...
  13. [13]
    [PDF] Referential Transparency, Definiteness and Unfoldability - ITU
    The present paper discusses referential transparency, referential opacity, and similar notions. Precise definitions are suggested in the context of a non-deter-.
  14. [14]
    [PDF] Mutable objects in R - Hadley Wickham
    Dec 15, 2010 · Code that uses immutable objects tends to be easier to reason about because effects are local. This is a big advantage: it is easier to ...Missing: benefits | Show results with:benefits
  15. [15]
  16. [16]
    [PDF] Exploring Language Support for Immutability
    May 8, 2016 · This means that in addition to not providing the expected benefits ... For example, the CERT C Secure Coding Standard [36] says “Immutable objects ...
  17. [17]
    3. Data model — Python 3.14.0 documentation
    Objects whose value can change are said to be mutable; objects whose value is unchangeable once they are created are called immutable. (The value of an ...
  18. [18]
  19. [19]
    Object (Java Platform SE 8 ) - Oracle Help Center
    If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer ...
  20. [20]
    [PDF] Generic Immutability and Nullity Types for an imperative object ...
    Jun 21, 2012 · Strong immutability is a very powerful concept, and is useful in several areas, for example: Concurrency If we know an object's values cannot ...
  21. [21]
    [PDF] The History of Standard ML - CMU School of Computer Science
    Mar 17, 2020 · The paper covers the early history of ML, the subsequent efforts to define a standard ML language, and the development of its major features and ...
  22. [22]
    [PDF] Immutable objects in Java - Semantic Scholar
    Shallow immutability too weak public /*@ immutable? @*/ class BankTransfer ... Deep immutability too strong public /*@ immutable?? @*/ BankTransfer ...
  23. [23]
    6.5 Aliasing and “Mutation at a Distance”
    Aliasing also exists for immutable data types, but in this case there is never any “action at a distance”, precisely because immutable values can never change.
  24. [24]
    Reading 21: Thread Safety - MIT
    Objectives. Recall that race conditions arise when multiple threads share the same mutable variable without coordinating what they're doing.
  25. [25]
    Implementing value objects - .NET - Microsoft Learn
    Sep 21, 2022 · Immutability is an important requirement. The values of a value object must be immutable once the object is created. Therefore, when the object ...Value Object Implementation... · Persist Value Objects As... · Additional Details On Owned...
  26. [26]
    Optimizing Immutable and Purity - Digital Mars
    Dec 22, 2008 · This is called common subexpression elimination. So far, so good. Let's now rewrite our example as: int bar(); int foo(int* a, int* b) { int ...
  27. [27]
  28. [28]
    [PDF] Ropes: an Alternative to Strings - Department of Computer Science
    Our data structure is quite different from that of Reference 17 to accommodate fast concatenation, the small list elements (characters), lazily evaluated.
  29. [29]
    [PDF] Effects of copy-on-write memory management on the response time ...
    Traditionally, UNIX systems actually copied the contents of the caller's address space to create the new process.
  30. [30]
    [PDF] A fork() in the road - Microsoft
    Even by 1979 (when the third BSD Unix introduced vfork() [15]) fork was seen as a performance problem, and only copy-on-write techniques [3, 72] kept its.
  31. [31]
    boost::shared_ptr class template
    If you are using unique() to implement copy on write, do not rely on a specific value when the stored pointer is zero. use_count. long use_count() const ...<|separator|>
  32. [32]
    String (Java SE 22 & JDK 22) - Oracle Help Center
    Returns the index of the first occurrence of the specified substring within the specified index range of this string. String. intern(). Returns a canonical ...
  33. [33]
    sys — System-specific parameters and functions — Python 3.14.0 ...
    This module provides access to some variables used or maintained by the interpreter and to functions that interact strongly with the interpreter.Sys.monitoring · Python Runtime Services · Fileinput · Audit events table
  34. [34]
    [PDF] Recursive Functions of Symbolic Expressions and Their ...
    In the LISP programming system we put more in the association list of a symbol than is required by the mathematical system described in the previous sections.<|separator|>
  35. [35]
    [PDF] H. Kaplan, Persistent Data Structures
    The structure is fully persistent if every version can be both. accessed and modified. The data structure is confluently persistent if it is fully persistent. ...
  36. [36]
    [PDF] Purely Functional Data Structures - CMU School of Computer Science
    Ironically, these techniques produce persistent data structures with amortized bounds, but the underlying data structure must be worst-case. (These ...
  37. [37]
    [PDF] Making Data Structures Persistent*
    An example of an access operation is a search for an item in a binary search tree. The accessed set forms a path in the tree that starts at the root and is ...
  38. [38]
    [PDF] Finger trees: a simple general-purpose data structure
    We introduce 2-3 finger trees, a functional representation of persistent sequences support- ing access to the ends in amortized constant time, and ...
  39. [39]
    Exploring Language Support for Immutability - ACM Digital Library
    For example, an immutable object can be shared safely among threads without locks, but a function that has a read-only reference to an object has no guarantee ...<|separator|>
  40. [40]
    [PDF] Object and Reference Immutability using Java Generics
    Mar 16, 2007 · Immutability information is useful in many software engineering tasks, such as modeling [7], verification [31], compile- and run- time ...
  41. [41]
    (PDF) Immutability and Design Patterns in Ruby - ResearchGate
    Apr 1, 2021 · Immutable Objects are thread safe by design. • They are simple to create and copy. • They do not need to ...
  42. [42]
    None
    Below is a merged summary of "Immutable Messages, Thread Safety, and Lock Avoidance in the Actor Model" based on Joe Armstrong’s 2003 Erlang Thesis. The response consolidates all information from the provided segments into a dense, structured format using tables in CSV style for clarity and completeness. Additional details, such as section references, examples, and URLs, are retained where provided.
  43. [43]
    Leveraging Immutability to Validate Hazard Pointers for Optimistic ...
    By leveraging immutability, a thread can validate from a marked node ... For safety, threads detaching a node protect nodes pointed by the detached node.<|control11|><|separator|>
  44. [44]
  45. [45]
    The not-so-final word on final #JVMLS - Inside.java
    Aug 12, 2025 · Immutability confers many advantages, since an immutable object ... optimizations (such as constant-folding). Moreover, initializaton of ...<|separator|>
  46. [46]
    [PDF] Fast and Lean Immutable Multi-Maps on the JVM based on ... - arXiv
    Aug 3, 2016 · These numbers confirm our intuition and are lower then the 20–40 % overhead reported by Steindorfer and Vinju [17]. The median costs for ...
  47. [47]
    How to Create an Immutable Class in Java - DigitalOcean
    Aug 6, 2025 · Here are a few strategies to test immutability: Check for field reassignments: Ensure all fields are private final . Try mutating returned ...
  48. [48]
    Mastering the Builder Pattern in Java: Why Immutability Matters
    Aug 12, 2025 · Step 1: Define the Immutable Invoice Class · It has a private constructor. · Its fields are final . · It does not expose any setters.
  49. [49]
    @Value - Project Lombok
    @Value is the immutable variant of @Data; all fields are made private and final by default, and setters are not generated.
  50. [50]
    Unsafe use of Reflection - OWASP Foundation
    This vulnerability is caused by unsafe use of the reflection mechanisms in programming languages like Java or C#.
  51. [51]
    [PDF] Javari: - Adding Reference Immutability to Java - DSpace@MIT
    Aug 22, 2006 · Non-conversion Must disallow the conversion, through assignment or unsafe casts, of a read-only reference to a mutable reference. This goal ...<|separator|>
  52. [52]
    SpotBugs is FindBugs' successor. A tool for static analysis ... - GitHub
    SpotBugs is FindBugs' successor. A tool for static analysis to look for bugs in Java code. - spotbugs/spotbugs.Releases 73 · SpotBugs Team · Spotbugs/sonar-findbugs · Issues 405
  53. [53]
    CWE-471: Modification of Assumed-Immutable Data (MAID) (4.18)
    Gain privileges by modifying assumed-immutable code addresses that are accessed by a driver. MAID issues can be primary to many other weaknesses, and they are ...
  54. [54]
    c# - Do not declare interfaces for immutable objects
    Mar 6, 2013 · In C#, a method that expects an object of an "immutable" type should not have a parameter of an interface type because C# interfaces cannot specify the ...At what point do immutable classes become a burden?Clean way to use mutable implementation of Immutable interfaces ...More results from softwareengineering.stackexchange.com
  55. [55]
    Writing Final Classes and Methods (The Java™ Tutorials > Learning ...
    A class that is declared final cannot be subclassed. This is particularly useful, for example, when creating an immutable class like the String class.
  56. [56]
    Chapter 4. Types, Values, and Variables - Oracle Help Center
    Certain variables that are not declared final are instead considered effectively final: A local variable whose declarator has an initializer (§14.4.2) is ...
  57. [57]
    Two Types of Variables | Scala Book
    like final in Java — and var makes a variable mutable. Because val fields can't ...
  58. [58]
    Case Classes | Tour of Scala
    Case classes are like regular classes with a few key differences which we will go over. Case classes are good for modeling immutable data.<|separator|>
  59. [59]
    JEP 359: Records (Preview) - OpenJDK
    Apr 19, 2019 · Records are a new type declaration in Java, a restricted class for shallowly immutable data, with a compact syntax and automatic members.
  60. [60]
  61. [61]
    A Strategy for Defining Immutable Objects (The Java™ Tutorials ...
    Don't provide methods that modify the mutable objects. · Don't share references to the mutable objects. Never store references to external, mutable objects ...Missing: design | Show results with:design
  62. [62]
    5 Creating Unmodifiable Lists, Sets, and Maps - Oracle Help Center
    An unmodifiable collection provides space efficiency benefits and prevents the collection from accidentally being modified, which might cause the program to ...Missing: design avoiding
  63. [63]
  64. [64]
  65. [65]
    dataclasses — Data Classes — Python 3.14.0 documentation
    The dataclasses module provides a decorator and functions to automatically add methods like __init__() and __repr__() to user-defined classes.Dataclasses -- Data Classes · Module Contents · Mutable Default Values
  66. [66]
    What's New In Python 3.12 — Python 3.14.0 documentation
    The undocumented keyword argument syntax for creating NamedTuple classes (for example, Point = NamedTuple("Point", x=int, y=int) ) has been deprecated since ...
  67. [67]
    const - JavaScript - MDN Web Docs - Mozilla
    Jul 8, 2025 · The const declaration declares block-scoped local variables. The value of a constant can't be changed through reassignment using the assignment operator.Try it · Syntax · Description · Examples
  68. [68]
    Object.freeze() - JavaScript - MDN Web Docs
    Sep 22, 2025 · The Object.freeze() static method freezes an object. Freezing an object prevents extensions and makes existing properties non-writable and non-configurable.Try it · Description · Examples
  69. [69]
    ECMAScript proposal for the Record and Tuple value types. | Stage 2
    Apr 15, 2025 · This proposal introduces two new deeply immutable data structures to JavaScript: Records and Tuples can only contain primitives and other Records and Tuples.Missing: 2024 | Show results with:2024
  70. [70]
    readonly keyword - C# reference - Microsoft Learn
    The `readonly` keyword in C# indicates that a field can only be assigned during declaration or in a constructor, and cannot be assigned after. It can also make ...Readonly field example · Readonly instance members
  71. [71]
    System.Collections.Immutable Namespace - Microsoft Learn
    Classes. ImmutableArray. Provides methods for creating an array that is immutable; meaning it cannot be changed once it is created.
  72. [72]
    Pattern matching overview - C# | Microsoft Learn
    Jan 27, 2025 · Pattern matching is a technique where you test an expression to determine if it has certain characteristics.Missing: immutable 2020s
  73. [73]
    Variables and Mutability - The Rust Programming Language
    Although variables are immutable by default, you can make them mutable by adding mut in front of the variable name as you did in Chapter 2.Missing: via | Show results with:via
  74. [74]
    References and Borrowing - The Rust Programming Language
    Spoiler alert: it doesn't work! Just as variables are immutable by default, so are references. We're not allowed to modify something we have a reference to.Missing: via | Show results with:via
  75. [75]
    Clone in std::clone - Rust
    A common trait that allows explicit creation of a duplicate value. Calling clone always produces a new value.
  76. [76]
    RefCell<T> and the Interior Mutability Pattern
    Interior mutability is a design pattern in Rust that allows you to mutate data even when there are immutable references to that data.
  77. [77]
    Match ergonomics reservations - The Rust Edition Guide
    Writing mut, ref, or ref mut on a binding is only allowed within a pattern when the pattern leading up to that binding is fully explicit (ie when it does not ...
  78. [78]
    3627-match-ergonomics-2024 - The Rust RFC Book
    On edition ≥ 2024, mut on an identifier pattern does not force its binding mode to by-value. On all editions, & patterns can match against &mut references.
  79. [79]
    An Introduction to Memory Safety Concepts and… - The AdaCore Blog
    Nov 10, 2023 · In Rust, variables are immutable by default, which helps to protect against unintended changes. The Rust compiler manages memory using a system ...
  80. [80]
    How Does Ada's Memory Safety Compare Against Rust? - ajxs.me
    Jan 17, 2025 · Rust is better at preventing common memory errors, but Ada avoids many by not using dynamic memory and formal proof of correctness.
  81. [81]
    Haskell Language
    The following function takes an integer and returns an integer. By the type it cannot do any side-effects whatsoever, it cannot mutate any of its arguments.Documentation · Log in · Downloads · Haskell Playground
  82. [82]
    3. Pure Functions, Laziness, I/O, and Monads - School of Haskell
    Dec 25, 2014 · One of the major strengths of Haskell is that the execution of pure functions can be easily parallelized because they have no side effects.
  83. [83]
    Lazy evaluation - Haskell « HaskellWiki
    Sep 15, 2025 · Technically, lazy evaluation means call-by-name plus sharing, a combination also referred to as call-by-need. In contrast, eager evaluation ...
  84. [84]
    Why Functional Programming? The Benefits of Referential ...
    Feb 2, 2018 · A follow-on effect of referential transparency is immutability. Any piece of code that mutates variables, objects, or data structures ...
  85. [85]
    Data.Foldable - Hackage - Haskell.org
    A more complex example is concatenation of a list of lists expressed as a nested right fold (bypassing ( ++ ) ). We can check that the definition is indeed lazy ...
  86. [86]
    11. Hints — Glasgow Haskell Compiler 9.8.1 User's Guide
    The GHC.Compact module provides a way to make garbage collection more efficient for long-lived data structures. Compacting a data structure collects the objects ...
  87. [87]
    Mutable and Immutable Collections - Scala Documentation
    Scala collections systematically distinguish between mutable and immutable collections. A mutable collection can be updated, reduced or extended in place.
  88. [88]
    Interacting with Java | Scala 3 — Book
    This page demonstrates how Scala code can interact with Java, and how Java code can interact with Scala code.Introduction · How to use Java collections in... · Extending Java interfaces in...
  89. [89]
    Enumerations
    An enumeration is used to define a type consisting of a set of named values. enum Color: case Red, Green, Blue This defines a new sealed class, Color.Missing: immutables 2021
  90. [90]
    JavaScript Object freeze() - Make Object Immutable - Vultr Docs
    Dec 2, 2024 · The Object.freeze() method in JavaScript is a powerful tool for making an object immutable. Once an object is frozen, you cannot add, delete, or modify its ...Missing: ES2025 proposals records
  91. [91]
  92. [92]
    Tuples and Records (Part 5): Performance Challenges - DZone
    Sep 15, 2025 · Tuples and Records were withdrawn from ES2025 due to performance and engine challenges. The ideas remain influential for immutability and value- ...Missing: freezing | Show results with:freezing<|separator|>
  93. [93]
    Immutable Struct in Golang - Stack Overflow
    Dec 4, 2017 · It is possible to make a struct read-only outside of its package by making its members non-exported and providing readers. For example:Which types are mutable and immutable in the Google Go Language?Idiomatic way to prevent modification to struct data membersMore results from stackoverflow.com
  94. [94]
    by-value struct with unexported fields - Google Groups
    Dec 1, 2009 · Immutable types fit right into Go, where they make sense as the values to pass on channels (since modifying a value while it is "en route ...
  95. [95]
    PHP RFC: Readonly classes
    Aug 4, 2021 · PHP 8.1 added support for readonly properties via PHP RFC: Readonly properties 2.0. However, it's still not easy to declare (quasi-)immutable classes.
  96. [96]
    Perl pragma to declare constants - Perldoc Browser
    The `constant` pragma allows declaring constants at compile-time, which are replaced with their value at compile time and can be optimized.Missing: immutability | Show results with:immutability
  97. [97]
    8 Utilities for Structs - Racket Documentation
    Essentially, a tupler carries most of the functionality an immutable struct definition creates except for its structure type descriptor. A tupler can only be ...
  98. [98]
    let vs var in Swift 5 [+differences and when to use each]
    Jan 2, 2021 · The let keyword in Swift allows you to create immutable variables. An immutable variable can be initialized only once and acts as a constant.
  99. [99]
    Why are structs in Swift said to be immutable?
    Feb 14, 2022 · Structs are not immutable. The thing about structs is that they are values. That means every variable is considered a copy, and its members are isolated from ...Missing: constants | Show results with:constants
  100. [100]
    The History of React.js on a Timeline - RisingStack Engineering
    May 30, 2024 · The History of React.js on a timeline: 2010-2018.The most significant milestones of its creation and development over the past 8 years.
  101. [101]
    Handling State in React: Four Immutable Approaches to Consider
    Jun 13, 2017 · Handling State in React: Four Immutable Approaches to Consider · Approach #1: Object.assign · Approach #2: Object Spread · Approach #3: ...Missing: adoption 2010s