# Looking for type-stable way to update several struct fields from NamedTuple

**URL:** <https://discourse.julialang.org/t/looking-for-type-stable-way-to-update-several-struct-fields-from-namedtuple/128182>\
**Category:** General Usage\
**Tags:** question\
**Created:** [April 18, 2025, 9:05am UTC](https://discourse.julialang.org/t/looking-for-type-stable-way-to-update-several-struct-fields-from-namedtuple/128182 "2025-04-18T09:05:33Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ickaser](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ickaser/32/28852_2.png) [@Ickaser](https://discourse.julialang.org/u/Ickaser)\
**Post date:** [April 18, 2025, 9:05am UTC](https://discourse.julialang.org/t/looking-for-type-stable-way-to-update-several-struct-fields-from-namedtuple/128182/1 "2025-04-18T09:05:33Z")

</div>

Hello,

I’ve been poring over docs for Accessors.jl, Setfield.jl, Parameters.jl, and Discourse, and haven’t found a clear answer to this question.

The problem I would like to solve is expressed by this MWE:

```julia
struct ParamObj
    a
    b
    c
end

function new_params(x, y)
    return (a=x, b=y)
end

po = ParamObj(1.0, 2.0, 3.0)
nt = new_params(4.0, 5.0)

po2 = nt_into_struct(po, nt)
# ParamObj(4.0, 5.0, 3.0)

```

where this imaginary function `nt_into_struct` takes all the fields of the NamedTuple and, a la Accessors.jl, produces a new instance where fields not in the NamedTuple come from the base object. Key here is that I may have several different functions producing these NamedTuples, which (I think) are each inferrable themselves but map to different fields of the struct, so I would like to programmatically assess which fields need to be set.

The best I could produce myself, using Accessors, is

```julia
function nt_into_struct(po, nt::NamedTuple)
    @warn "Copying arbitrary NamedTuple into struct. Type unstable. If doing this repeatedly, define a new method for copy_nt_into_struct" nt
    po_new = deepcopy(po)
    for (k, v) in zip(keys(nt), values(nt))
        po_new = set(po_new, PropertyLens{k}(), v)
    end
    return po_new
end

```

which does the job but is type-unstable, which is not acceptable for me since this is going to be in a hot inner loop.  
I can write new methods like

```julia
function nt_into_struct(po, nt::NamedTuple{(:a, :b)})
    po_new = deepcopy(po)
    @reset po_new.a = nt.a
    @reset po_new.b = nt.b
    return po_new
end

```

but then I have to write each of these methods manually; I can deal with that but feel like there ought to be a more elegant solution, especially since this will be specific to the ordering of parameters in the NamedTuple.  
I can imagine a macro that generates new methods of `nt_into_struct` like this, but don’t feel confident enough to have tried that yet.

A function like [reconstruct](https://mauro3.github.io/Parameters.jl/stable/api/#Parameters.reconstruct), which allows `reconstruct(po; nt...)` from Parameters.jl would do the trick, but the docs there warn that it is slow and to look at Setfield.jl.

I have the feeling that I am missing something obvious here (like maybe all my structs here should just be NamedTuples, in which case I can use `merge`.)

---

<div class="post-metadata">

**Author:** ![KnutAM](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/knutam/32/37720_2.png) [@KnutAM](https://discourse.julialang.org/u/KnutAM)\
**Post date:** [April 18, 2025, 9:33am UTC](https://discourse.julialang.org/t/looking-for-type-stable-way-to-update-several-struct-fields-from-namedtuple/128182/2 "2025-04-18T09:33:53Z")

</div>

I’ve used the following code, still requires one method per struct (unless you know the type won’t change, but I guess you expect that since you mention type stability?)

```julia
julia> @kwdef struct ParamObj{TA,TB,TC}
           a::TA
           b::TB
           c::TC
       end

julia> struct_to_namedtuple(x::T) where T = NamedTuple{fieldnames(T)}(tuple((getproperty(x,k) for k in fieldnames(T))...));

julia> nt_into_struct(s::ParamObj, nt) = ParamObj(;struct_to_namedtuple(s)..., nt...)
nt_into_struct (generic function with 1 method)

julia> po = ParamObj(1.0, 2.0, 3.0);

julia> nt = (a = 1, b = "b");

julia> new_po = nt_into_struct(po, nt)
ParamObj{Int64, String, Float64}(1, "b", 3.0)

```

---

<div class="post-metadata">

**Author:** ![Ickaser](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ickaser/32/28852_2.png) [@Ickaser](https://discourse.julialang.org/u/Ickaser)\
**Post date:** [April 18, 2025, 9:37am UTC](https://discourse.julialang.org/t/looking-for-type-stable-way-to-update-several-struct-fields-from-namedtuple/128182/3 "2025-04-18T09:37:11Z")

</div>

Not a bad idea. In my case I have a small number (maybe 2-3) of structs that would need this method, and a potentially larger number of kinds of NamedTuples, so the burden of adding a new method per type is minimal.

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [April 18, 2025, 9:38am UTC](https://discourse.julialang.org/t/looking-for-type-stable-way-to-update-several-struct-fields-from-namedtuple/128182/4 "2025-04-18T09:38:20Z")

</div>

Sounds like you want `setproperties(obj, nt)` from ConstructionBase.jl.

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [April 18, 2025, 9:39am UTC](https://discourse.julialang.org/t/looking-for-type-stable-way-to-update-several-struct-fields-from-namedtuple/128182/5 "2025-04-18T09:39:12Z")

</div>

> [@KnutAM](#):
>
> `struct_to_namedtuple(x::T) where T = NamedTuple{fieldnames(T)}(tuple((getproperty(x,k) for k in fieldnames(T))...));`

This is `getproperties(x)` btw 🙂

---

<div class="post-metadata">

**Author:** ![Ickaser](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ickaser/32/28852_2.png) [@Ickaser](https://discourse.julialang.org/u/Ickaser)\
**Post date:** [April 18, 2025, 9:52am UTC](https://discourse.julialang.org/t/looking-for-type-stable-way-to-update-several-struct-fields-from-namedtuple/128182/6 "2025-04-18T09:52:02Z")

</div>

It makes me so happy to learn these kinds of elegant solutions already exist, and to get an answer within an hour!
