# Immutable types

**URL:** <https://discourse.julialang.org/t/immutable-types/97751>\
**Category:** General Usage\
**Created:** [April 21, 2023, 5:36pm UTC](https://discourse.julialang.org/t/immutable-types/97751 "2023-04-21T17:36:57Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![lancejnelson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lancejnelson/32/21898_2.png) [@lancejnelson](https://discourse.julialang.org/u/lancejnelson)\
**Post date:** [April 21, 2023, 5:36pm UTC](https://discourse.julialang.org/t/immutable-types/97751/1 "2023-04-21T17:36:57Z")

</div>

I have an immutable struct designed like this:

```julia
struct crystal
    lVecs::Matrix{Float64}
    nBasis:: Vector{Int64}
    latpar::Float64
    atomicBasis::Vector{Matrix{Float64}}
    coordSys::Vector{String}
end

```

and an instance of that type called `myCrystal`. I’m having a hard time understanding why the following is allowed:

```julia
myCrystal.nBasis .= [1,4,8]

```

but this is not:

```julia
myCrystal.nBasis = [1,4,8]

```

What aspects exactly of an immutable type are immutable? I suppose I couldn’t change the type of variable or the size/shape, but as long as I’m only mutating values I’m OK?

---

<div class="post-metadata">

**Author:** ![jakobnissen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jakobnissen/32/13477_2.png) [@jakobnissen](https://discourse.julialang.org/u/jakobnissen)\
**Post date:** [April 21, 2023, 5:46pm UTC](https://discourse.julialang.org/t/immutable-types/97751/2 "2023-04-21T17:46:30Z")

</div>

You can’t replace any of the fields of an immutable type. Hence, when you do

```julia
myCrystal.nBasis = [1,4,8]

```

it fails, because you are trying to take a new array (namely `[1,4,8]`) and assigning it to a field of an immutable struct.

The thing that may confuse you is that immutable structs can have mutable structs as fields. So, in your example, you can’t mutate a `crystal` since it’s immutable, but you CAN mutate a `Vector{Int64}`, and therefore you can mutate `crystal.nBasis`, including changing its size and data content.

It’s not possible to declare a struct “recursively immutable”.

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [April 21, 2023, 10:14pm UTC](https://discourse.julialang.org/t/immutable-types/97751/3 "2023-04-21T22:14:47Z")

</div>

It’s never possible to modify an object that is an instance of an immutable type. These kinds of objects are sometimes also called immutable objects.

The part that I think may be confusing here is that immutable objects may contain _references_. A reference may refer to a mutable object, which may be mutated even though a reference to it is contained in some immutable object.

The terminology is perhaps confusing/imprecise because the same exact situation will sometimes be described as a mutable object being contained in another object, while on another occasion one would say that just the reference is what’s contained in the parent object.

> [@jakobnissen](#):
>
> It’s not possible to declare a struct “recursively immutable”.

I think it is possible to enforce `isbits` status in an inner constructor, though, thus ensuring that all instances of the type are “recursively immutable”. (Except that incomplete initialization may be used to punch a hole through that, maybe.)

---

<div class="post-metadata">

**Author:** ![David\_Sagan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/david_sagan/32/33792_2.png) [@David\_Sagan](https://discourse.julialang.org/u/David_Sagan)\
**Post date:** [April 22, 2023, 6:05am UTC](https://discourse.julialang.org/t/immutable-types/97751/4 "2023-04-22T06:05:41Z")

</div>

You cannot modify the components of an immutable type but if a component is mutable you can modify the components of this component. Thus:

```julia
julia> struct A; x; end

julia> mutable struct B; y; end

julia> a=A(B(3))
A(B(3))

julia> a.x = B(7) # Bad! Cannot redefine a component (x here) of an immutable struct 
ERROR: setfield!: immutable struct of type A cannot be changed
Stacktrace:
 [1] setproperty!(x::A, f::Symbol, v::B)
   @ Base ./Base.jl:39
 [2] top-level scope
   @ REPL[6]:1

julia> a.x.y = 7 # Good! Redefinition of components of a.x (a mutable struct) is OK
7

```

Similarly, if you go back to your original example, you cannot redefine myCrystal.nBasis but you can redefine the components of myCrystal.nBasis. That is, this is OK:

```julia
myCrystal.nBasis[1] = 1 
myCrystal.nBasis[2] = 4 
myCrystal.nBasis[3] = 8

```

which is equivalent to `myCrystal.nBasis .= [1,4,8]`.

Notice that trying to change the size of the vector of myCrystal.nBasis is not possible due to the immutability of the `crystal` struct.

From the manual [Types · The Julia Language](https://docs.julialang.org/en/v1/manual/types/)

- For composite types, this (immutability) means that the identity of the values of its fields will never change. When the fields are bits types, that means their bits will never change, for fields whose values are mutable types like arrays, **that means the fields will always refer to the same mutable value even though that mutable value’s content may itself be modified.** (emphesis added)
