# Mutable struct pitfall

**URL:** <https://discourse.julialang.org/t/mutable-struct-pitfall/44996>\
**Category:** General Usage\
**Created:** [August 15, 2020, 3:14pm UTC](https://discourse.julialang.org/t/mutable-struct-pitfall/44996 "2020-08-15T15:14:36Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![j2b2](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/j2b2/32/3387_2.png) [@j2b2](https://discourse.julialang.org/u/j2b2)\
**Post date:** [August 15, 2020, 3:14pm UTC](https://discourse.julialang.org/t/mutable-struct-pitfall/44996/1 "2020-08-15T15:14:36Z")

</div>

```julia
julia> mutable struct S x::Int end
julia> a = S(3)
S(3)
julia> b = a
S(3)
julia> b.x = 5
5
julia> a
S(5)

```

Where is it documented ? Every computer scientist is aware of the risks when writing `b = a`, and then modifiying elements of `b`, when `a` is an _array_; but seriously who knows that the pb is the same with _mutable struct_ ?

You don’t imagine how much time I spent to discover and understand very subtle anomalies in a somewhat complex program, where some variables were cached in dictionaries, that evolved mysteriously because some of them were these _evil mutable struct_…

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [August 15, 2020, 3:23pm UTC](https://discourse.julialang.org/t/mutable-struct-pitfall/44996/2 "2020-08-15T15:23:48Z")

</div>

As you noted, when doing `a = b`, `a` and `b` reference the same object (mutable or not, this is always true)

Therefore, the effect you observed is true for anything mutable in julia. `Dict`s, `Array`s, `Set`s, etc… since `a` _is_ `b`, mutating one is mutating the other.

---

<div class="post-metadata">

**Author:** ![johnmyleswhite](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/johnmyleswhite/32/31_2.png) [@johnmyleswhite](https://discourse.julialang.org/u/johnmyleswhite)\
**Post date:** [August 15, 2020, 3:32pm UTC](https://discourse.julialang.org/t/mutable-struct-pitfall/44996/3 "2020-08-15T15:32:29Z")

</div>

Can you give examples of popular languages where this isn’t what happens?

Your example seems like it’s what happens with Python’s classes, for example:

```julia
>>> class Foo:
... def __init__ (self, x):
... self.x = x
...
>>> a = Foo(1)
>>> b = a
>>>
>>> a.x
1
>>> b.x
1
>>>
>>> b.x = 2
>>>
>>> a.x
2
>>> b.x
2

```

---

<div class="post-metadata">

**Author:** ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)\
**Post date:** [August 15, 2020, 3:45pm UTC](https://discourse.julialang.org/t/mutable-struct-pitfall/44996/4 "2020-08-15T15:45:42Z")

</div>

So the simple solution is: Don’t use evil mutable structs. Use immutable structs instead.

---

<div class="post-metadata">

**Author:** ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)\
**Post date:** [August 15, 2020, 3:47pm UTC](https://discourse.julialang.org/t/mutable-struct-pitfall/44996/5 "2020-08-15T15:47:12Z")

</div>

Since @johnmyleswhite replied, maybe it’s a good moment to refer to this old-but-still-very-relevant post of his:

> **[Values vs. Bindings: The Map is Not the Territory](https://www.johnmyleswhite.com/notebook/2014/09/06/values-vs-bindings-the-map-is-not-the-territory/)**
>
> Many newcomers to Julia are confused by the seemingly dissimilar behaviors of the following two functions:
> julia\> a = \[1, 2, 3\] 3-element Array{Int64,1}: 1 2 3 julia\> function foo!(a) a\[1\] = 10 return end foo! (generic function with 1 method)...

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [August 15, 2020, 3:51pm UTC](https://discourse.julialang.org/t/mutable-struct-pitfall/44996/6 "2020-08-15T15:51:08Z")

</div>

> [@j2b2](#):
>
> Where is it documented?

`?=`:

> `=` is the assignment operator.
> 
> - For variable a and expression b, a = b makes a refer to the value of b.

> [@j2b2](#):
>
> who knows that the pb is the same with _mutable struct_?

Almost all Julia users I assume, since it is the same semantics for _all_ values. After `a = b`, no valid program should be able to distinguish `a` from `b`, ie `a === b`.

> [@dpsanders](#):
>
> Don’t use evil mutable structs

Incidentally, I wish we had `evil` as a syntax qualifier, as in

```julia
evil mutable struct S
    x::Int
end

evil function foo(x::Int)
    x + 1
end

```

I am still not quite sure what it would do though, but we could think of something.

---

<div class="post-metadata">

**Author:** ![j2b2](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/j2b2/32/3387_2.png) [@j2b2](https://discourse.julialang.org/u/j2b2)\
**Post date:** [August 15, 2020, 4:37pm UTC](https://discourse.julialang.org/t/mutable-struct-pitfall/44996/7 "2020-08-15T16:37:14Z")

</div>

> [@johnmyleswhite](#):
>
> Can you give examples of popular languages where this isn’t what happens?

I didn’t see the keyword `struct` outside the C language, and in this case assignment is a copy.

---

<div class="post-metadata">

**Author:** ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)\
**Post date:** [August 15, 2020, 4:46pm UTC](https://discourse.julialang.org/t/mutable-struct-pitfall/44996/8 "2020-08-15T16:46:02Z")

</div>

> [@j2b2](#):
>
> I didn’t see the keyword `struct` outside the C language, and in this case assignment is a copy.

In julia it is the same. That is, assignment of immutable struct is a copy. `mutable struct` means “pointer to heap-allocated struct with C layout, but everything managed by the julia garbage collector + allocator please”.

Structure layout is julia tries to be mostly C compatible (in-order, same alignment rules, …). Mutable structs, as “proper reified objects”, have an identity, a type-tag and a memory address (except if the compiler figures out that it can get away without assigning an address because nobody uses it…).

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [August 15, 2020, 4:56pm UTC](https://discourse.julialang.org/t/mutable-struct-pitfall/44996/9 "2020-08-15T16:56:14Z")

</div>

> [@foobar\_lv2](#):
>
> That is, assignment of immutable struct is a copy.

No, no, no. It works semantically exactly the same as for mutable structures. The rest is compiler optimizations.

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [August 15, 2020, 10:57pm UTC](https://discourse.julialang.org/t/mutable-struct-pitfall/44996/10 "2020-08-15T22:57:24Z")

</div>

> [@j2b2](#):
>
> I didn’t see the keyword `struct` outside the C language, and in this case assignment is a copy.

Fair enough. I think Java has similar behavior but they use the keyword `class` instead. If you want to think in terms of C `struct`s, maybe the most sane analogy is that the problem is not the `struct` itself (mutable or immutable), but that all variables in Julia are NOT names of positions of memory, but instead, names of pointers to the memory. So, if your swap two variables i.e., `a, b = b, a` you just swap pointers instead (often you do not even pay the price of a pointer swap, the compiler elides this).

This is the best I can do using concepts of C, the truly best would be learning how Julia has bindings and not variables. @yuyichao has been answering [this question for years](https://discourse.julialang.org/t/variable-binding-re-assignment-argument-passing-let-scope/16840/5). If they give a reference (maybe to a post of them), I will always link it whenever I see a variation of this question.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [August 15, 2020, 11:24pm UTC](https://discourse.julialang.org/t/mutable-struct-pitfall/44996/11 "2020-08-15T23:24:07Z")

</div>

> [@Tamas\_Papp](#):
>
> Incidentally, I wish we had `evil` as a syntax qualifier, as in
> 
> ```julia
> evil mutable struct S
> x::Int
> end
> 
> evil function foo(x::Int)
> x + 1
> end
> 
> ```
> 
> I am still not quite sure what it would do though, but we could think of something.

Oh that’s a delightful idea. Pretty easy to cook up at least on the documentation level as well:

```julia
julia> macro evil(ex)
           quote
               """
                   $($(repr(ex))) 
        
               This is evil, avoid it!
               """
               $ex
           end |> esc
       end
@evil (macro with 1 method)

julia> @evil mutable struct S
           x::Int
       end
S

help?> S
search: S Sys Set SVD sum sin sec Some svd sum! step stat sqrt sort skip size sinh sind sinc sign show seek sech secd svd! Schur

  :(mutable struct S
    #= REPL[1]:2 =#
    x::Int

  end) 

  This is evil, avoid it!

julia> @evil function foo(x::Int) = x + 1
ERROR: syntax: unexpected "="
Stacktrace:
 [1] top-level scope at none:1

julia> @evil foo(x::Int) = x + 1
foo

help?> foo
search: foo floor pointer_from_objref OverflowError RoundFromZero unsafe_copyto! functionloc StackOverflowError @functionloc

  :(foo(x::Int) = begin
        #= REPL[4]:1 =#
        x + 1
    end)

  This is evil, avoid it!

```

---

<div class="post-metadata">

**Author:** ![Jeff\_Emanuel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff_emanuel/32/15440_2.png) [@Jeff\_Emanuel](https://discourse.julialang.org/u/Jeff_Emanuel)\
**Post date:** [August 16, 2020, 2:39am UTC](https://discourse.julialang.org/t/mutable-struct-pitfall/44996/12 "2020-08-16T02:39:50Z")

</div>

Since you asked, FWIW, struct assignment in Go is a copy. I suppose C and C++ are still popular and they behave the same. You would assign pointers (or references in C++) to have two variables reference the same instance.

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [August 16, 2020, 6:06am UTC](https://discourse.julialang.org/t/mutable-struct-pitfall/44996/13 "2020-08-16T06:06:05Z")

</div>

> [@j2b2](#):
>
> Every computer scientist is aware of the risks when writing `b = a` , and then modifiying elements of `b` , when `a` is an _array_ ; but seriously who knows that the pb is the same with _mutable struct_ ?

Isn’t an array a mutable struct?

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [August 16, 2020, 8:02am UTC](https://discourse.julialang.org/t/mutable-struct-pitfall/44996/14 "2020-08-16T08:02:36Z")

</div>

> [@Jeff\_Emanuel](#):
>
> FWIW, struct assignment in Go is a copy

I think that their “struct assignment” is not Julia’s `=`, it is closer in spirit to something like `.=`.

I think the misunderstanding in this topic comes from some languages allowing sophisticated semantics for `a = b`, with eg C++ allowing full overloading so that literally anything can happen, including side effects etc.

In contrast, Julia’s `=` is simple: all `a = b` does is ensure `a === b` — no tricks, just a few corner cases like [type declarations](https://docs.julialang.org/en/v1/manual/types/#Type-Declarations-1).

> **example**
>
> ```julia
> julia> function f(x)
> local y::Float64
> y = x
> x ≡ y
> end
> f (generic function with 1 method)
> 
> julia> f(1)
> false
> 
> julia> f(1.0)
> true
> 
> ```

---

<div class="post-metadata">

**Author:** ![j2b2](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/j2b2/32/3387_2.png) [@j2b2](https://discourse.julialang.org/u/j2b2)\
**Post date:** [August 16, 2020, 9:07am UTC](https://discourse.julialang.org/t/mutable-struct-pitfall/44996/15 "2020-08-16T09:07:24Z")

</div>

Julia language has a beautiful design, and is quick. That’s why I use it, without understanding (ot trying to understand) its internal structure. I think (and hope) I’m not the only one in this situation. Something like :

> the truly best would be learning how Julia has bindings and not variables. @yuyichao has been answering this question for years

isn’t for me – I tried to read it, unsuccessfully ☹

Why there are both `struct` and `mutable struct` was obviously surprising, so I _read the doc_ : [https://docs.julialang.org/en/v1/manual/types/#Mutable-Composite-Types-1](https://docs.julialang.org/en/v1/manual/types/#Mutable-Composite-Types-1). It’s well written and interesting, but doesn’t warn users about the pitfall that’s the subject of this conversation.

Sure using two names for an array, a dictionary, and so on, is hazardous, but any programmer with some experience knows that. At the opposite any programmer with some experience is aware of the composite data type _struct_ when using the C language, that’s why I think Julia documentation should be completed.

Have a nice sunday !

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [August 16, 2020, 9:35am UTC](https://discourse.julialang.org/t/mutable-struct-pitfall/44996/16 "2020-08-16T09:35:22Z")

</div>

> [@j2b2](#):
>
> but doesn’t warn users about the pitfall that’s the subject of this conversation.

Since you just encountered this problem, you still remember why you found it confusing, so it would be great if you could contribute to the docs.

I suspect that the _Types_ section may not be the best place for this, since it is really general to assignment. Note that the [Noteworthy differences from C/C++](https://docs.julialang.org/en/v1/manual/noteworthy-differences/#Noteworthy-differences-from-C/C-1) has

> Julia arrays are not copied when assigned to another variable. After `A = B` , changing elements of `B` will modify `A` as well. Updating operators like `+=` do not operate in-place, they are equivalent to `A = A + B` which rebinds the left-hand side to the result of the right-hand side expression.

and

> Julia values are not copied when assigned or passed to a function. If a function modifies an array, the changes will be visible in the caller.

Perhaps these could be reworded from “arrays” to “containers (including arrays and mutable structs)”.

---

<div class="post-metadata">

**Author:** ![Jeff\_Emanuel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff_emanuel/32/15440_2.png) [@Jeff\_Emanuel](https://discourse.julialang.org/u/Jeff_Emanuel)\
**Post date:** [August 16, 2020, 2:50pm UTC](https://discourse.julialang.org/t/mutable-struct-pitfall/44996/17 "2020-08-16T14:50:23Z")

</div>

Yes, that’s all true. I’m not making a case for or against how Julia works, just answering the question. Every language is different. One of the most important features to understand when learning a new language is its uses of value vs reference semantics.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [August 16, 2020, 5:17pm UTC](https://discourse.julialang.org/t/mutable-struct-pitfall/44996/18 "2020-08-16T17:17:58Z")

</div>

> [@j2b2](#):
>
> Julia language has a beautiful design, and is quick. That’s why I use it, without understanding (ot trying to understand) its internal structure.

Julia makes that easy. There are no copy constructor or move constructors etc. Assignment is always a no-op. It always just binds the symbol to the object on the right hand side. No implicit copies. Same when passing arguments to functions.
