Concepts
Immutable variables
In imperative programming, values held in program variables whose content never changes are known as ''Weak vs strong immutability
Sometimes, one talks of certain ''fields'' of an object being immutable. This means that there is no way to change those parts of the object state, even though other parts of the object may be changeable (''weakly immutable''). If all fields are immutable, then the object is immutable. If the whole object cannot be extended by another class, the object is called ''strongly immutable''. This might, for example, help to explicitly enforce certain invariants about certain data in the object staying the same through the lifetime of the object. In some languages, this is done with a keyword (e.g.const
in C++, final
in Java) that designates the field as immutable. Some languages reverse it: in mutable
to be so.
References to objects
In mostReferencing vs copying objects
If an object is known to be immutable, it is preferred to create a reference of it instead of copying the entire object. This is done to conserve memory by preventing data duplication and avoid calls to constructors and destructors; it also results in a potential boost in execution speed. The reference copying technique is much more difficult to use for mutable objects, because if any user of a mutable object reference changes it, all other users of that reference see the change. If this is not the intended effect, it can be difficult to notify the other users to have them respond correctly. In these situations, defensive copying of the entire object rather than the reference is usually an easy but costly solution. The observer pattern is an alternative technique for handling changes to mutable objects.Copy-on-write
A technique that blends the advantages of mutable and immutable objects, and is supported directly in almost all modern hardware, is copy-on-write (COW). Using this technique, when a user asks the system to copy an object, it instead merely creates a new reference that still points to the same object. As soon as a user attempts to modify the object through a particular reference, the system makes a real copy, applies the modification to that, and sets the reference to refer to the new copy. The other users are unaffected, because they still refer to the original object. Therefore, under COW, all users appear to have a mutable version of their objects, although in the case that users do not modify their objects, the space-saving and speed advantages of immutable objects are preserved. Copy-on-write is popular in virtual memory systems because it allows them to save memory space while still correctly handling anything an application program might do.Interning
The practice of always using references in place of copies of equal objects is known as '' interning''. If interning is used, two objects are considered equal if and only if their references, typically represented as pointers or integers, are equal. Some languages do this automatically: for example, Python automatically interns short strings. If the algorithm that implements interning is guaranteed to do so in every case that it is possible, then comparing objects for equality is reduced to comparing their pointers – a substantial gain in speed in most applications. (Even if the algorithm is not guaranteed to be comprehensive, there still exists the possibility of a fast path case improvement when the objects are equal and use the same reference.) Interning is generally only useful for immutable objects.Thread safety
Immutable objects can be useful in multi-threaded applications. Multiple threads can act on data represented by immutable objects without concern of the data being changed by other threads. Immutable objects are therefore considered more '' thread-safe'' than mutable objects.Violating immutability
Immutability does not imply that the object as stored in the computer's memory is unwriteable. Rather, immutability is a compile-time construct that indicates what a programmer can do through the normal interface of the object, not necessarily what they can absolutely do (for instance, by circumventing the type system or violating const correctness in C or C++).Language-specific details
In Python, Java and the StringBuffer
and StringBuilder
In computer programming, a string is traditionally a sequence of characters, either as a literal constant or as some kind of variable. The latter may allow its elements to be mutated and the length changed, or it may be fixed (after creation). ...
(mutable versions of Java ) and in .NET this is bytearray
.
Additionally, all of the primitive wrapper classes in Java are immutable.
Similar patterns are the Ada
In Ada, any object is declared either ''variable'' (i.e. mutable; typically the implicit default), orconstant
(i.e. immutable) via the constant
keyword.
C#
In C# you can enforce immutability of the fields of a class with thereadonly
statement.
By enforcing all the fields as immutable, you obtain an immutable type.
C++
In C++, a const-correct implementation ofCart
would allow the user to create instances of the class and then use them as either const
(immutable) or mutable, as desired, by providing two different versions of the items()
method. (Notice that in C++ it is not necessary — and in fact impossible — to provide a specialized constructor for const
instances.)
mutable
keyword, which lets a member variable be changed from within a const
method.
D
In D, there exist two type qualifiers,const
and immutable
, for variables that cannot be changed.D Language Specification § 18const
, Java's final
, and C#'s readonly
, they are transitive and recursively apply to anything reachable through references of such a variable. The difference between const
and immutable
is what they apply to: const
is a property of the variable: there might legally exist mutable references to referred value, i.e. the value can actually change. In contrast, immutable
is a property of the referred value: the value and anything transitively reachable from it cannot change (without breaking the type system, leading to undefined behavior). Any reference of that value must be marked const
or immutable
. Basically for any unqualified type T
, const(T)
is the disjoint union of T
(mutable) and immutable(T)
.
C
object, its mField
can be written to. For a const(C)
object, mField
cannot be modified, it inherits const
; iField
is still immutable as it is the stronger guarantee. For an immutable(C)
, all fields are immutable.
In a function like this:
c
might refer to the same object as m
, so mutations to m
could indirectly change c
as well. Also,
c
might refer to the same object as i
, but since the value then is immutable, there are no changes. However, m
and i
cannot legally refer to the same object.
In the language of guarantees, mutable has no guarantees (the function might change the object), const
is an outward-only guarantee that the function will not change anything, and
immutable
is a bidirectional guarantee (the function will not change the value and the caller must not change it).
Values that are const
or immutable
must be initialized by direct assignment at the point of declaration or by a const
parameters forget if the value was mutable or not, a similar construct, inout
, acts, in a sense, as a variable for mutability information.
A function of type const(S) function(const(T))
returns const(S)
typed values for mutable, const and immutable arguments. In contrast, a function of type inout(S) function(inout(T))
returns S
for mutable T
arguments, const(S)
for const(T)
values, and immutable(S)
for immutable(T)
values.
Casting immutable values to mutable inflicts undefined behavior upon change, even if the original value comes from a mutable origin. Casting mutable values to immutable can be legal when there remain no mutable references afterward. "An expression may be converted from mutable (...) to immutable if the expression is unique and all expressions it transitively refers to are either unique or immutable." If the compiler cannot prove uniqueness, the casting can be done explicitly and it is up to the programmer to ensure that no mutable references exist.
The type string
is an alias for immutable(char)[]
, i.e. a typed slice of memory of immutable characters. Making substrings is cheap, as it just copies and modifies a pointer and a length filed, and safe, as the underlying data cannot be changed. Objects of type const(char)[]
can refer to strings, but also to mutable buffers.
Making a shallow copy of a const or immutable value removes the outer layer of immutability: Copying an immutable string (immutable(char[])
) returns a string (immutable(char)[]
). The immutable pointer and length are being copied and the copies are mutable. The referred data has not been copied and keeps its qualifier, in the example immutable
. It can be stripped by making a depper copy, e.g. using the dup
function.
Java
A classic example of an immutable object is an instance of the JavaString
class
toLowerCase()
does not change the data "ABC" that s
contains. Instead, a new String object is instantiated and given the data "abc" during its construction. A reference to this String object is returned by the toLowerCase()
method. To make the String s
contain the data "abc", a different approach is needed:
s
references a new String object that contains "abc". There is nothing in the syntax of the ''declaration'' of the class String that enforces it as immutable; rather, none of the String class's methods ever affect the data that a String object contains, thus making it immutable.
The keyword final
( detailed article) is used in implementing immutable primitive types and object references, but it cannot, by itself, make ''the objects themselves'' immutable. See below examples:
Primitive type variables (int
, long
, short
, etc.) can be reassigned after being defined. This can be prevented by using final
.
final
keyword. final
only prevents reassignment.
Integer
, Long
, Short
, Double
, Float
, Character
, Byte
, Boolean
) are also all immutable. Immutable classes can be implemented by following a few simple guidelines.
JavaScript
In JavaScript, all primitive types (Undefined, Null, Boolean, Number, BigInt, String, Symbol) are immutable, but custom objects are generally mutable.const
declaration doesn't mean that value of the read-only reference is immutable, just that the name cannot be assigned to a new value.
Perl
In Perl, one can create an immutable class with the Moo library by simply declaring all the attributes read only:Python
In Python, some built-in types (numbers, booleans, strings, tuples, frozensets) are immutable, but custom classes are generally mutable. To simulate immutability in a class, one could override attribute setting and deletion to raise exceptions:collections.namedtuple
dataclasses
dataclasses
will override __setattr__()
and __delattr__()
to raise FrozenInstanceError
if invoked.
Racket
mcons
, mcar
, set-mcar!
etc. In addition, many immutable types are supported, for example, immutable strings and vectors, and these are used extensively. New structs are immutable by default, unless a field is specifically declared mutable, or the whole struct:
Rust
Rust'smut
keyword.Scala
In Scala, any entity (narrowly, a binding) can be defined as mutable or immutable: in the declaration, one can useval
(value) for immutable entities and var
(variable) for mutable ones. Note that even though an immutable binding can not be reassigned, it may still refer to a mutable object and it is still possible to call mutating methods on that object: the ''binding'' is immutable, but the underlying ''object'' may be mutable.
For example, the following code snippet:
maxValue
(the integer type is inferred at compile-time) and a mutable entity named currentValue
.
By default, collection classes such as List
and Map
are immutable, so update-methods return a new instance rather than mutating an existing one. While this may sound inefficient, the implementation of these classes and their guarantees of immutability mean that the new instance can re-use existing nodes, which, especially in the case of creating copies, is very efficient.
See also
* Clojure * Erlang * F# * Haskell * Mutator method * Prolog * Scala * TclReferences
''This article contains some material from theExternal links
{{Wiktionary, mutable