# Mutating a flag in a nonmutating struct

**URL:** <https://discourse.julialang.org/t/mutating-a-flag-in-a-nonmutating-struct/132341>\
**Category:** General Usage\
**Tags:** question, internals\
**Created:** [September 13, 2025, 9:41am UTC](https://discourse.julialang.org/t/mutating-a-flag-in-a-nonmutating-struct/132341 "2025-09-13T09:41:45Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![mesonepigreco](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mesonepigreco/32/46262_2.png) [@mesonepigreco](https://discourse.julialang.org/u/mesonepigreco)\
**Post date:** [September 13, 2025, 9:41am UTC](https://discourse.julialang.org/t/mutating-a-flag-in-a-nonmutating-struct/132341/1 "2025-09-13T09:41:45Z")

</div>

Dear Julia Community.  
I have a struct that contains both Bool flags and arrays.  
I want to be able to change the value of some of the Bool flags, but I would like to avoid having a mutable struct, which I believe can create problems like type instability (where the type of the elements could change at runtime, since I need to define it with abstract types for generality)

This is an example:

```julia-auto
mutable struct StochasticSettings{T}
    remove_scha_forces :: Bool
    clean_start_gradient_centroids :: Bool
    clean_start_gradient_fcs :: Bool
    initialized :: Bool
    original_force :: Array{T}
    original_fc_gradient :: Array{T}
end

```

Now, This is currently a mutable struct, since I would like to change the value of initialized, however, I would like to have it immutable, as the Array{T} is generic and could be reallocated at runtime, so keeping it mutable I believe this could create unwanted type instability. I also want to avoid being more specific here (e.g. using a concrete type for the arrays), as based on some condition in the initialization, the type and ranks of the Array could change during the initialization.

Indeed, a working solution is to use a 1-length Bool array for initialized, but it is not really elegant. Does it exists an automatic wrapper on something like this (i.e., like a pointer to a single element)?

---

<div class="post-metadata">

**Author:** ![karei](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/karei/32/214809_2.png) [@karei](https://discourse.julialang.org/u/karei)\
**Post date:** [September 13, 2025, 10:13am UTC](https://discourse.julialang.org/t/mutating-a-flag-in-a-nonmutating-struct/132341/2 "2025-09-13T10:13:33Z")

</div>

**Option A** : Use `const` on array fields inside a mutable struct

```julia
mutable struct StochasticSettings{T}
    remove_scha_forces :: Bool
    clean_start_gradient_centroids :: Bool
    clean_start_gradient_fcs :: Bool
    initialized :: Bool
    const original_force :: Array{T}
    const original_fc_gradient :: Array{T}
end

```

**Option B** : Embed a mutable struct inside an immutable wrapper, and flatten fields with ForwardMethods.jl

```julia
using ForwardMethods

mutable struct StochasticSettings
    remove_scha_forces :: Bool
    clean_start_gradient_centroids :: Bool
    clean_start_gradient_fcs :: Bool
    initialized :: Bool
end

struct StochasticParam{T}
    settings :: StochasticSettings
    original_force :: Array{T}
    original_fc_gradient :: Array{T}
end

@define_interface StochasticParam interface = properties delegated_fields = (settings,)

x = StochasticParam(...)
x.remove_scha_forces = true # OK

```

**Option C** : Use `Base.RefValue`

```julia
struct StochasticSettings{T}
    remove_scha_forces :: Base.RefValue{Bool}
    clean_start_gradient_centroids :: Base.RefValue{Bool}
    clean_start_gradient_fcs :: Base.RefValue{Bool}
    initialized :: Base.RefValue{Bool}
    original_force :: Array{T}
    original_fc_gradient :: Array{T}
end

x = StochasticParam(...)
x.remove_scha_forces[] = true

```

A related discussion on using `Base.RefValue` inside immutable structs:  
[https://discourse.julialang.org/t/ref-t-vs-base-refvalue-t/127886](https://discourse.julialang.org/t/ref-t-vs-base-refvalue-t/127886)

**Option D** : Using Accessors.jl

```julia
using Accessors

struct StochasticSettings{T}
    remove_scha_forces :: Bool
    clean_start_gradient_centroids :: Bool
    clean_start_gradient_fcs :: Bool
    initialized :: Bool
    original_force :: Array{T}
    original_fc_gradient :: Array{T}
end

s = StochasticSettings(...)
s2 = @set s.initialized = true
s2.original_force === s.original_force # true

```

The arrays are not deep-copied.

I would choose Option B. But it’s difficult for me to evaluate the performance of different options.

---

<div class="post-metadata">

**Author:** ![Gesee](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gesee/32/217235_2.png) [@Gesee](https://discourse.julialang.org/u/Gesee)\
**Post date:** [September 13, 2025, 11:46am UTC](https://discourse.julialang.org/t/mutating-a-flag-in-a-nonmutating-struct/132341/3 "2025-09-13T11:46:36Z")

</div>

My solution is kind of hard but if I had your problem, that’s what I would have done.  
First of all I would have made a completely immutable struct with parametric types for arrays:

```julia
struct StochasticSettings{T} # T <: Array
    remove_scha_forces :: Bool
    clean_start_gradient_centroids :: Bool
    clean_start_gradient_fcs :: Bool
    initialized :: Bool
    original_force :: T
    original_fc_gradient :: T
end

```

Then I would define accessors functions

```julia
settings = setinitialized(old_settings, true) # the arrays will just be copied

```

This method should be done only if performance are critical. If not the solutions provided by the others are 100% fine

---

<div class="post-metadata">

**Author:** ![rveltz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rveltz/32/2707_2.png) [@rveltz](https://discourse.julialang.org/u/rveltz)\
**Post date:** [September 13, 2025, 12:21pm UTC](https://discourse.julialang.org/t/mutating-a-flag-in-a-nonmutating-struct/132341/4 "2025-09-13T12:21:52Z")

</div>

use `Accessors.jl`

`@reset mystruct.flag = true` or `newstruct = @set mystruct.flag = true`

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [September 13, 2025, 12:39pm UTC](https://discourse.julialang.org/t/mutating-a-flag-in-a-nonmutating-struct/132341/5 "2025-09-13T12:39:02Z")

</div>

This is akin to an [XY problem](https://xyproblem.info/): you are trying to solve the wrong problem here, because the premise of the question has a fundamental misunderstanding.

> [@mesonepigreco](#):
>
> but I would like to avoid having a mutable struct, which I believe can create problems like type instability (where the type of the elements could change at runtime, since I need to define it with abstract types for generality)

Mutability vs immutability has nothing to do with type instabilities. If you have abstractly typed fields, it is type-unstable whether or not the struct is mutable.

The way to get both concrete types and generality is to define parametric structs, as you have attempted here with `{T}`. This can be done for both immutable and mutable types.

> [@mesonepigreco](#):
>
> as the Array{T} is generic and could be reallocated at runtime, so keeping it mutable I believe this could create unwanted type instability.

No. A parametric type like `StochasticSettings{T}` is not a single type, it is a _family_ of types. e.g. when you initialize it with `Vector{Float64}`, you get a `StochasticSettings{Float64}` instance where the fields can _only_ be `Array{Float64}`.

However, `Array{Float64}` is still abstractly typed, because it doesn’t include the dimensionality. To make it concrete, while remaining mutable, I would change it to `Vector{T}` in your definition (assuming you want only 1d arrays). You could make it even more generic with e.g.

```julia-auto
mutable struct StochasticSettings{T <: AbstractArray}
    remove_scha_forces :: Bool
    clean_start_gradient_centroids :: Bool
    clean_start_gradient_fcs :: Bool
    initialized :: Bool
    original_force :: T
    original_fc_gradient :: T
end

```

which allows any type of array of any type of element and any dimensionality (replace with `AbstractVector` if you only want 1d arrays) … but the type is fixed for any single `StochasticSettings{T}` instance.

It’s really critical to understand this in order to get good performance in Julia.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [September 13, 2025, 1:04pm UTC](https://discourse.julialang.org/t/mutating-a-flag-in-a-nonmutating-struct/132341/6 "2025-09-13T13:04:18Z")

</div>

> [@mesonepigreco](#):
>
> mutable struct, which I believe can create problems like type instability (where the type of the elements could change at runtime, since I need to define it with abstract types for generality)

Superficially, an immutable object’s fields’ runtime types don’t change because its fields don’t directly change, but if you constrain the field with an abstract _declared_ type like `Array{T}` (an iterated union via unspecified `N`), then that’s what the compiler’s type inference has to work with, not the runtime value’s type. To use a simpler example, `Some{Number}(1)` and `Some{Number}(1.0)` both provide the compiler with the same immutable type `Some{Number}` regardless of the field’s type at runtime, `typeof(something(s))`. The mutability or immutability of `StochasticSettings` doesn’t actually matter here, your specified generality is the true cause.

It might not even help if you parameterize `StochasticSettings` to have concrete declared types because variables or expressions bound to instances of varying concrete `StochasticSettings` types for generality are also type unstable. The upside is a function call taking such instances as inputs can be internally type-stable even if the call site is type-unstable; this is called a function barrier in the Manual’s Performance Tips. You won’t even have to change `StochasticSettings` to leverage function barriers if you are mostly passing the `original_force` and `original_fc_gradient` arrays into performance critical function calls. A little bit of well-isolated type instability can be well worth the generality; to put some numbers on it, if 99% of your runtime is spent on internally type-stable function calls, then optimizing away the type instabilities and runtime dispatches in the other 1% of caller functions would only speed up the program by \<(100/99-1)=1.01%.
