Option A: Use const
on array fields inside a mutable struct
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
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
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
Option D: Using Accessors.jl
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.