# Dynamically create Struct

**URL:** <https://discourse.julialang.org/t/dynamically-create-struct/108259>\
**Category:** General Usage\
**Tags:** question, struct\
**Created:** [January 2, 2024, 11:29am UTC](https://discourse.julialang.org/t/dynamically-create-struct/108259 "2024-01-02T11:29:04Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![fdekerme](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fdekerme/32/43574_2.png) [@fdekerme](https://discourse.julialang.org/u/fdekerme)\
**Post date:** [January 2, 2024, 11:29am UTC](https://discourse.julialang.org/t/dynamically-create-struct/108259/1 "2024-01-02T11:29:04Z")

</div>

Hello everyone 😁!

I am working on a compartment model for a Markov chain simulation. The parameters of the compartment model (name of each compartment and transition matrix) are defined in an excel file. A `Compartment_Model` is composed of several `Compartment`’s defined with the following `Struct`’s :

```julia
mutable struct Compartment
    name::String
    id::Int16

    initial_particle_number::Float64
    mean_residence_time::Float64
    connected_compartments_id:: Vector{Int16}
    transition_probabilities:: Vector{Float16}
end

Base.@kwdef struct Compartment_Model
    c1::Compartment
    c2::Compartment
    c3::Compartment
    c4::Compartment
    c5::Compartment

    compartment_list::Vector{Compartment} = [c1, c2,c3, c4, c5]
    correspondance_dict::Dict{Int16, Compartment} = Dict([compartment.id => compartment for compartment in compartment_list])
    total_number_of_particle::Float64 = sum([compartment.initial_particle_number for compartment in compartment_list])
    initial_particle_distribution::Vector{Float64} = [compartment.initial_particle_number/total_number_of_particle for compartment in compartment_list]
end

```

However, this method is not flexible because I have to manually rewrite `Compartment_Model` in the code if I change the input model from the Excel file. My question is: Is it possible to dynamically create `Compartment`s from the data in the Excel file and create a `Compartment_Model` with them?  
It might be possible to do something like that with macros, but I can’t see exactly how.

Thanks ! 😁  
fdekerm

---

<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:** [January 2, 2024, 11:44am UTC](https://discourse.julialang.org/t/dynamically-create-struct/108259/2 "2024-01-02T11:44:13Z")

</div>

> [@fdekerme](#):
>
> have to manually rewrite `Compartment_Model` in the code if I change the input model from the Excel file

Rewrite and change how? It’s not readily apparent how you would rewrite `Compartment_Model` and dynamically create `Compartment`, or how that differs from the structure in the provided example. Describe what can vary and what can stay the same, the latter could lend to optimizations.

---

<div class="post-metadata">

**Author:** ![greatpet](https://avatars.discourse-cdn.com/v4/letter/g/e495f1/32.png) [@greatpet](https://discourse.julialang.org/u/greatpet)\
**Post date:** [January 2, 2024, 12:38pm UTC](https://discourse.julialang.org/t/dynamically-create-struct/108259/3 "2024-01-02T12:38:25Z")

</div>

In the interest of maintainability, code generation is usually the last resort. Consider using Named Tuples or even dictionaries as alternatives to a generated struct.

---

<div class="post-metadata">

**Author:** ![mrufsvold](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrufsvold/32/31600_2.png) [@mrufsvold](https://discourse.julialang.org/u/mrufsvold)\
**Post date:** [January 2, 2024, 12:57pm UTC](https://discourse.julialang.org/t/dynamically-create-struct/108259/4 "2024-01-02T12:57:40Z")

</div>

NamedTuple behaves like a dynamically created Struct, so that’s what you’re after! You just need to make your `Compartment_Model` parametric instead of hard coding the name `::Compartment` for the field types.

---

<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:** [January 2, 2024, 1:37pm UTC](https://discourse.julialang.org/t/dynamically-create-struct/108259/5 "2024-01-02T13:37:59Z")

</div>

`NamedTuple` is also immutable, though, and `Compartment` is mutable; a closer alternative would be MutableNamedTuples.jl or a `Dict` for structural mutation. Making many different `NamedTuple` types also requires compilation of methods for each one; we don’t know enough about the situation to tell what would be better. Right now it’s entirely possible that the only thing that changes are the values, in which case it’s a matter of reading a file and instantiation, or the only thing that changes is the number of `Compartment`s and very often, in which case removing the `c1` to `c5` fields is enough.

---

<div class="post-metadata">

**Author:** ![mrufsvold](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrufsvold/32/31600_2.png) [@mrufsvold](https://discourse.julialang.org/u/mrufsvold)\
**Post date:** [January 2, 2024, 6:10pm UTC](https://discourse.julialang.org/t/dynamically-create-struct/108259/6 "2024-01-02T18:10:58Z")

</div>

> [@fdekerme](#):
>
> are defined in an excel file

My read of the situation is that there is an Excel file with headers that serves as input to the model, but that those headers are static for than run. But you’re absolutely right that that was an unchecked assumption – my bad!

Re: mutability, I also just missed that. Thank you for the catch. A side question for me: do we know if there is a significant difference in performance between a mutable struct with concete types for its fields an vs a NamedTuple of `Ref{T}` values (where `T` is concrete)?

---

<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:** [January 2, 2024, 6:41pm UTC](https://discourse.julialang.org/t/dynamically-create-struct/108259/7 "2024-01-02T18:41:05Z")

</div>

> [@mrufsvold](#):
>
> difference in performance between a mutable struct with concete types for its fields an vs a NamedTuple of `Ref{T}` values (where `T` is concrete)

Yeah, the performance characteristics could differ for sure. One could sort of say that a mutable struct is like a pointer to an immutable struct, while an immutable tuple of `Ref`s is like an immutable tuple of pointers. So there’s extra inefficiency in the representation with the latter option, if nothing else.

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [January 2, 2024, 7:57pm UTC](https://discourse.julialang.org/t/dynamically-create-struct/108259/8 "2024-01-02T19:57:53Z")

</div>

Why not use a normal `NamedTuple` and update it with `setproperties` from ConstructionBase.jl or `@set` from Setfield.jl or Accessors.jl?

That will be _much_ faster than the other two options, doesn’t allocate, works on GPUs, yada yada.

---

<div class="post-metadata">

**Author:** ![bobcassels](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bobcassels/32/14586_2.png) [@bobcassels](https://discourse.julialang.org/u/bobcassels)\
**Post date:** [January 2, 2024, 10:17pm UTC](https://discourse.julialang.org/t/dynamically-create-struct/108259/9 "2024-01-02T22:17:59Z")

</div>

I have used XLSX.jl to read an Excel file, and then used Julia metaprogramming to build code after parsing the Excel cells using Meta.parse(). This was a straightforward use of metaprogramming.

I didn’t follow enough of the discussion to have an opinion about what sort of Julia code you should generate.

---

<div class="post-metadata">

**Author:** ![BambOoxX](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bambooxx/32/22179_2.png) [@BambOoxX](https://discourse.julialang.org/u/BambOoxX)\
**Post date:** [January 3, 2024, 12:24am UTC](https://discourse.julialang.org/t/dynamically-create-struct/108259/10 "2024-01-03T00:24:55Z")

</div>

On my side, I’ve been generating structs using a macro from XML files. This allows me to create structs subtyping an `AbstractObject` with some specific values coming from the XML files. I have no clue if it is better than using a Dict or else, but it sure looks like what you are trying to do.

---

<div class="post-metadata">

**Author:** ![fdekerme](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fdekerme/32/43574_2.png) [@fdekerme](https://discourse.julialang.org/u/fdekerme)\
**Post date:** [January 4, 2024, 10:17am UTC](https://discourse.julialang.org/t/dynamically-create-struct/108259/11 "2024-01-04T10:17:33Z")

</div>

Thanks for the answers !  
As some of you have suggested, I tried to use a `NamedTuple`.  
Here a simplified code if someone else is interested (with the `Compartment` structure defined in the original post)` :

```julia
function load_compartment_model(compartment_models_data_path)
    transition_probability_matrix, compartment_names = load_markov_chain_data(compartment_models_data_path)
    compartment_names_symbol = Vector{Symbol}(undef, length(compartment_names))
    compartment_list = Vector{Compartment}(undef, length(compartment_names))

    for (id, name) in enumerate(compartment_names)
        compartment_list[id] = Compartment(name, transition_probability_matrix)
        compartment_names_symbol[id] = Symbol(name)
    end

    compartment_model = NamedTuple{Tuple(compartment_names_symbol)}(compartment_list)
    return compartment_model
end

```

It seems to work as I want!  
Could you elaborate a little bit about `setproperties` ? I don’t understand how it works.

Thanks !  
fdekerm

---

<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:** [January 4, 2024, 11:52am UTC](https://discourse.julialang.org/t/dynamically-create-struct/108259/12 "2024-01-04T11:52:11Z")

</div>

> [@fdekerme](#):
>
> Here a simplified code

Constructing a `Dict`, and converting it to `NamedTuple` (if the dictionary is not already OK for you), would be nicer IMO. Something like this:

```julia
function load_compartment_model(transition_probability_matrix, compartment_names)
    d = Dict{Symbol,Compartment}()
    for name ∈ compartment_names
        d[Symbol(name)] = Compartment(name, transition_probability_matrix)
    end
    (; d...)
end

```

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [January 4, 2024, 1:53pm UTC](https://discourse.julialang.org/t/dynamically-create-struct/108259/13 "2024-01-04T13:53:10Z")

</div>

`ConstructionBase.setproperties` is a function that lets you update most immutable objects in-place by passing in a “patch” `NamedTuple` - fields in the patch will be updated in the target object and the whole thing is rebuilt. This normally has no runtime cost.

`@set` from Accessors.jl or Setfiled.jl (and most functions from packages that do rebuilding of immutable things) use `Constructionbase.setproperties` under the hood. `@set` is just a convenience macro to make the syntax easier.

The use-case is if you need to modify your model after construction - don’t use a mutable object, it will be much slower, use an immutable object and rebuild it as needed.

It seems counter intuitive that rebuilding is faster than setting a field. But in julia no actual rebuild happens in practice because immutable objects usually don’t really exist as you think they do. Its just registers being moved around. Setting a mutable field has to actually write to some specific bit memory.
