# Metaprogramming - Unpack/pack struct-fields based on symbols

**URL:** <https://discourse.julialang.org/t/metaprogramming-unpack-pack-struct-fields-based-on-symbols/28322>\
**Category:** General Usage\
**Tags:** macros, metaprogramming\
**Created:** [September 3, 2019, 11:52am UTC](https://discourse.julialang.org/t/metaprogramming-unpack-pack-struct-fields-based-on-symbols/28322 "2019-09-03T11:52:49Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![mrVeng](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrveng/32/8836_2.png) [@mrVeng](https://discourse.julialang.org/u/mrVeng)\
**Post date:** [September 3, 2019, 11:52am UTC](https://discourse.julialang.org/t/metaprogramming-unpack-pack-struct-fields-based-on-symbols/28322/1 "2019-09-03T11:52:49Z")

</div>

Hi everyone,

I would like pack/unpack (I am using the excellent Parameters package macros for this) specific fields of a struct within a function. I created example code here:

```julia
using Parameters
using Distributions

#construct example struct
mutable struct Model{E<:VariateForm, F<:VariateForm}
    α :: Vector{<:Distribution{E}} # Transition
    β :: Vector{<:Distribution{F}} # Observation
end
#test
model = Model( [Categorical([.5,.5]), Categorical([.5,.5])], [Normal(), Normal()])
info = fieldnames(Model)

function update!(model::Model, info) #Not Working
################# Unpack all model parameter that are in info field
#Not Working
    for i in eachindex(info)
        @unpack @eval $(info[i]) = model
    end

################# #Do something - just exemplary here to get different output
#Working
@eval $(info[1]) = [Normal(1,2), Gamma(1,2)]
@eval $(info[2]) = [Poisson(1), Normal(3,4)]

################# Pack all model parameter that are in info field
#Not Working
for i in eachindex(info)
    @pack! model = @eval $(info[i])
end

end

```

**Question 1:** I would like to unpack all the fields that come from a specific tuple but calling both  
`@unpack` and `@eval` simultaneously does not seem to work, even though calling both individually works. Does anyone know a solution if I would be forced to call 2 macros simultaneously?

**Question 2:** On a related note, does anyone have a method to just unpack all parameter of a general struct?

Best regards,

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [September 3, 2019, 12:39pm UTC](https://discourse.julialang.org/t/metaprogramming-unpack-pack-struct-fields-based-on-symbols/28322/2 "2019-09-03T12:39:17Z")

</div>

Are you aware of `@eval`s limitations? For instance that it will evaluate in global scope (i.e. module scope) even when called inside a function?

For gymnastics like you do, you should consider using a Dict where you can access the keys (i.e. your variables) and the values.

Q2: Did you consider using the `@with_kw` macro of Parameters.jl and the using `@unpack_MyStruct`?

Q1: `@unpack` needs on its left hand side the names of the variable to unpack, as syntax (macros only work on syntax)

---

<div class="post-metadata">

**Author:** ![mrVeng](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrveng/32/8836_2.png) [@mrVeng](https://discourse.julialang.org/u/mrVeng)\
**Post date:** [September 3, 2019, 12:54pm UTC](https://discourse.julialang.org/t/metaprogramming-unpack-pack-struct-fields-based-on-symbols/28322/3 "2019-09-03T12:54:19Z")

</div>

Thank you for your answer! I saw in the docs that one may use the `@unpack_*` for `@with_kw` structs, I was wondering if it might also be possible for general containers.

I read that `@eval` will evaluate in the global scope, but so far it was the only way for me to call and assign values to symbols like this:

```julia
@eval $(info[1]) = [Normal(1,2), Gamma(1,2)]

```

I dont really understand why `dicts` would be better in this case as I would also only collect the symbols from there. The `Model` struct is quite a bit bigger in the real code and I perform many operations on it. I can always dispatch `update!` on different subtypes of it, but if more Models become available I ideally would have a more general `update!` function where I dont need to more and more code to it but instead generically updates based on some information.

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [September 3, 2019, 1:07pm UTC](https://discourse.julialang.org/t/metaprogramming-unpack-pack-struct-fields-based-on-symbols/28322/4 "2019-09-03T13:07:46Z")

</div>

> [@mrVeng](#):
>
> I was wondering if it might also be possible for general containers.

No, this cannot be achieved with a macro as this only has information on the syntax. When a macro sees `a`, it only sees `:a` and not its contents (the macro is evaluated before `a` gets its contents). Thus it could not know what fields `a` has to unpack.

Using `eval`s, in particular in local scopes such as functions, is considered bad style. Further it makes Julia slow as it cannot reason about types anymore (see performance section, about global variables applies here as well). Another reason is that you can get name-clashes, say your `info` contains a field which is identical to a global variable of yours, bam:

```julia
module A
cabbage(x) = 2 # so cabbage is a global
function f(inp)
  @eval $inp = 7
  return nothing
end
end
using .A
A.f(:lettuce) # ok
A.f(:cabbage) # error: ERROR: invalid redefinition of constant cabbage

```

So, your `info` structs interact in a non-trivial way with the rest of your code, changing either can lead to breakage.

Anyway, your line would read:

```julia
opts = Dict{Symbol,Any}()
opts[info[1]] = [Normal(1,2), Gamma(1,2)]

```

which looks nicer too and equally addresses “but instead generically updates based on some information.”

---

<div class="post-metadata">

**Author:** ![mrVeng](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrveng/32/8836_2.png) [@mrVeng](https://discourse.julialang.org/u/mrVeng)\
**Post date:** [September 3, 2019, 1:19pm UTC](https://discourse.julialang.org/t/metaprogramming-unpack-pack-struct-fields-based-on-symbols/28322/5 "2019-09-03T13:19:50Z")

</div>

Thanks for your explanation!

So, afaik, instead of using macros I could build a Dict with they `info` keys and some values, and then loop through a mutable struct to update information, and to avoid ambiguity?

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [September 3, 2019, 1:28pm UTC](https://discourse.julialang.org/t/metaprogramming-unpack-pack-struct-fields-based-on-symbols/28322/6 "2019-09-03T13:28:30Z")

</div>

Yes, that sounds ok.
