# Nested struct or something else?

**URL:** <https://discourse.julialang.org/t/nested-struct-or-something-else/51604>\
**Category:** New to Julia\
**Created:** [December 10, 2020, 1:00pm UTC](https://discourse.julialang.org/t/nested-struct-or-something-else/51604 "2020-12-10T13:00:22Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![mocalvao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mocalvao/32/19318_2.png) [@mocalvao](https://discourse.julialang.org/u/mocalvao)\
**Post date:** [December 10, 2020, 1:00pm UTC](https://discourse.julialang.org/t/nested-struct-or-something-else/51604/1 "2020-12-10T13:00:23Z")

</div>

In a certain program, I need to cater with a model `M :=(omega, eos)`, where `omega:=(omega_1,... omega_P)` and `eos:=(eos_1,..., eos_Q)` are “lists” of `P` and `Q` real parameters, with `P` known in advance (at compile time), but `Q` only at run time. The whole model `M` or its “component lists”, `omega` or `eos`, by themselves, appear in several functions, either as explicit or implicit arguments.

In fact, I have, at least, two physically well-motivated situations where either `Q` is 2 or 3; thus I thought of defining Julia `struct`’s such that:

```julia
using Parameters

@with_kw struct Omega{T<;Real}
  omega_1 = 70.0
  ...
  omega_P = 0.7
end

@with_kw Eos1{T<:Real}
  w_0 = -1.0
  w_a = 0.0
end

@with_kw Eos2{T<:Real}
  A = 0.5
  z_f = -1.9
  z_t = 1.7
end

Eos = Union(Eos1, Eos2)

#and finally:

@with_kw struct ModelM
  omega::Omega
  eos::Eos
end

```

With these types, I hope to be able to easily define my functions such that there are not too many explicit called arguments and, at the same time, I am still able to use them conveniently for \_integration, optimization, plotting, etc, on the parameters above (omega\_1,…,omega\_P, w\_0, w\_a, A, z\_f, z\_t), by choosing conveniently the fields of the different `struct`’s thus defined, via `@unpack` and/or `Ref`.  
**Question 1:** Does this seem to be a good strategy?

Explicitly, sometimes I will have functions such as;

```julia
function distance(z, m::ModelM)
 #function body
end

```

**Question 2:** Should I explicitly indicate the type for `m`? For me, it seems to help legibility a bit, but I wonder about performance…

Some other times, my functions are just explicit functions of only eos::Eos, not of omega::Omega, such as:

```julia
function piezoenergeticratio(z, omega)
# function body
end

```

Finally,  
**Question 3:** I wonder whether sometimes it would be cumbersome to access the nested `struct` fields and whether an altogether distinct approach would be wiser, declaring the functions with all explicit arguments (with variable number of them and somehow “flattened”). Is this the case?

Any pointers for documentation or packages, relevant corresponding comments or general coding advice are deeply appreciated!

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [December 10, 2020, 2:37pm UTC](https://discourse.julialang.org/t/nested-struct-or-something-else/51604/2 "2020-12-10T14:37:02Z")

</div>

> [@mocalvao](#):
>
> **Question 2:** Should I explicitly indicate the type for `m` ? For me, it seems to help legibility a bit, but I wonder about performance…

That won’t affect performance. It might be useful to debug the code.

Concerning the general question, maybe this thread helps, particularly what I have marked as a solution to it, which is the possibility of writing function-like objects. The types of structures of objects and functions to achieve what you want are all there, I think: [Define data-dependent function, various ways](https://discourse.julialang.org/t/define-data-dependent-function-various-ways/48988)

---

<div class="post-metadata">

**Author:** ![mocalvao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mocalvao/32/19318_2.png) [@mocalvao](https://discourse.julialang.org/u/mocalvao)\
**Post date:** [December 10, 2020, 9:01pm UTC](https://discourse.julialang.org/t/nested-struct-or-something-else/51604/3 "2020-12-10T21:01:36Z")

</div>

@lmiq Thank you for your info about question 2 and general advice directing to another post here at Discourse; I will have to ponder over it. What about questions 1 and 3?

---

<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:** [December 10, 2020, 10:14pm UTC](https://discourse.julialang.org/t/nested-struct-or-something-else/51604/4 "2020-12-10T22:14:10Z")

</div>

Your question 1 and 3 are kinda vague.

> [@mocalvao](#):
>
> **Question 1:** Does this seem to be a good strategy?

To know if a strategy is good or not someone needs to understand where it will be used, and if its weakpoints are not a problem given the circumstances. The way you used `Eos` and `Omega` in `ModelM` makes both fields of `ModelM` to be not-concrete. This has some performance penalties, but if this is not your bottleneck, then there is no problem. I just recommend to you that, when you access the fields, you pass them to a function that do the heavy work (instead of doing the heavy work directly in that function), so you do not have to deal with type unstability in the code that does the heavy work.

> [@mocalvao](#):
>
> **Question 3:** I wonder whether sometimes it would be cumbersome to access the nested `struct` fields and whether an altogether distinct approach would be wiser, declaring the functions with all explicit arguments (with variable number of them and somehow “flattened”). Is this the case?

I do not think so. Your second scenario seems to be a scope nightmare. Just use `@unpack` for easy access (from the package with the same name if I am not wrong).

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [December 10, 2020, 10:22pm UTC](https://discourse.julialang.org/t/nested-struct-or-something-else/51604/5 "2020-12-10T22:22:00Z")

</div>

> [@mocalvao](#):
>
> ```julia
> 
> @with_kw Eos1{T<:Real}
> w_0 ::T = -1.0 
> w_a ::T = 0.0
> end
> 
> @with_kw Eos2{T<:Real}
> A :: T = 0.5
> z_f :: T = -1.9
> z_t :: T = 1.7
> end
> 
> Eos = Union(Eos1, Eos2) # could be an abstract type as well
> 
> #and finally:
> 
> @with_kw struct ModelM{T1<:Eos, T2} # This is important for type stability
> omega::Omega{T2}
> eos::T1
> end
> 
> ```

As Henrique mentioned, the other questions are somewhat vague. But I have made some changes to the code above to improve the syntax.

Some small things:

You probably want just

```julia
@with_kw Eos1
  w_0::Float64 = -1.0 
  w_a::Float64 = 0.0
end

```

(not `T<:Real`). You can initialize `Eos1` with an integer anyway, and that will be more transparent and less error prone in terms of type stability.

Concerning the general question, the most common answer to it is the use of closures. Using a struct to carry the data is fine. But you will find many cases in Julia like:

```julia
julia> inner(f,x) = f(x) 

julia> function outer(f,x)
         inner(f,x)
       end
outer (generic function with 1 method)

julia> g(x,data) = data*x
g (generic function with 1 method)

julia> const mydata = 5.
5.0

julia> x = 10.
10.0

julia> outer(x -> g(x,mydata), x)
50.0

```

As you can see, the “multiple parameters” represented here by `mydata` can be fed only to the anonymous function `x->g(x,mydata)` which is an argument of the `outer` function, and what is passed along is the function itself.
