# Convert or Reinterpret Between NamedTuple and SVector

**URL:** <https://discourse.julialang.org/t/convert-or-reinterpret-between-namedtuple-and-svector/134600>\
**Category:** Performance\
**Tags:** namedtuple, staticarrays, generated\
**Created:** [December 16, 2025, 11:03pm UTC](https://discourse.julialang.org/t/convert-or-reinterpret-between-namedtuple-and-svector/134600 "2025-12-16T23:03:25Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![cortner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cortner/32/204_2.png) [@cortner](https://discourse.julialang.org/u/cortner)\
**Post date:** [December 16, 2025, 11:03pm UTC](https://discourse.julialang.org/t/convert-or-reinterpret-between-namedtuple-and-svector/134600/1 "2025-12-16T23:03:25Z")

</div>

My question is related to [Vector to NamedTuple?](https://discourse.julialang.org/t/vector-to-namedtuple/20683)

Assume my `NamedTuple` contains only floating point values `T` and `SVector{N, T}` entries, e.g.,

```julia
using StaticArrays 
nt = ( a = rand(), b = SA[1.0, 2.0 ,3.0] )

```

Taking such a `NamedTuple` and interpreting it as an `SVector` is straightforward

```julia
v = reinterpret(SVector{4, Float64}, nt)

```

I can write a `@generated` function that does the reverse, but it is awful (see below) and I just wondered whether is a more straightforward way to achieve this?

```julia
@generated function _svec2nt(v::SVector, x::NamedTuple) 
   SYMS = fieldnames(x)
   TT = fieldtypes(x)

   _len(::Type{T}) where {T <: Number} = 1
   _len(::Type{SVector{N, T}}) where {N, T <: Number} = N

   i0 = Int[] 
   idx = 1 
   for T in TT
      push!(i0, idx) 
      idx += _len(T)
   end
   push!(i0, idx) 

   # indexing into v::SVector 
   inds = [] 
   for i = 1:length(TT) 
      rg = i0[i]:i0[i+1]-1
      if length(rg) == 1 
         push!(inds, "$(first(rg))")
      else 
         rg = SVector(rg...)
         push!(inds, "SA$rg")
      end
   end

   code = "(; "
   for (sym, ind) in zip(SYMS, inds)
      code *= "$sym = v[$ind], "
   end 
   code *= ")"

   return quote 
      $(Meta.parse(code))
   end
end 

```

---

<div class="post-metadata">

**Author:** ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)\
**Post date:** [December 16, 2025, 11:26pm UTC](https://discourse.julialang.org/t/convert-or-reinterpret-between-namedtuple-and-svector/134600/2 "2025-12-16T23:26:58Z")

</div>

Rather than crafting a statement for parsing, you can use a `NamedTuple` constructor directly, just find the segments of the vector

```julia-auto
julia> NamedTuple{fieldnames(typeof(nt)), Tuple{fieldtypes(typeof(nt))...}}((v[1], v[2:4]))
(a = 0.31259929654404184, b = [1.0, 2.0, 3.0])

```

or even just

```julia-auto
julia> typeof(nt)((v[1], v[2:4]))

```

But you need a small program to find the indices `1` and `2:4`.

---

<div class="post-metadata">

**Author:** ![cortner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cortner/32/204_2.png) [@cortner](https://discourse.julialang.org/u/cortner)\
**Post date:** [December 17, 2025, 12:35am UTC](https://discourse.julialang.org/t/convert-or-reinterpret-between-namedtuple-and-svector/134600/3 "2025-12-17T00:35:28Z")

</div>

That doesn’t sound conceptually easier or clearer. I was hoping some trick that exploits how these objects just occupy the same memory.

---

<div class="post-metadata">

**Author:** ![matthias314](https://avatars.discourse-cdn.com/v4/letter/m/a88e4f/32.png) [@matthias314](https://discourse.julialang.org/u/matthias314)\
**Post date:** [December 17, 2025, 12:52am UTC](https://discourse.julialang.org/t/convert-or-reinterpret-between-namedtuple-and-svector/134600/4 "2025-12-17T00:52:42Z")

</div>

If you want, you can again use `reinterpret`:

```julia-auto
julia> nt = ( a = rand(), b = SA[1.0, 2.0 ,3.0] )
(a = 0.4808058471551182, b = [1.0, 2.0, 3.0])

julia> v = reinterpret(SVector{4, Float64}, nt)
4-element SVector{4, Float64} with indices SOneTo(4):
 0.4808058471551182
 1.0
 2.0
 3.0

julia> reinterpret(typeof(nt), Tuple(v))
(a = 0.4808058471551182, b = [1.0, 2.0, 3.0])

```

For some reason, one has to use `Tuple(v)` instead of `v`.

---

<div class="post-metadata">

**Author:** ![cortner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cortner/32/204_2.png) [@cortner](https://discourse.julialang.org/u/cortner)\
**Post date:** [December 17, 2025, 1:32am UTC](https://discourse.julialang.org/t/convert-or-reinterpret-between-namedtuple-and-svector/134600/5 "2025-12-17T01:32:57Z")

</div>

That’s what I was missing. Thanks!

---

<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:** [December 17, 2025, 4:09am UTC](https://discourse.julialang.org/t/convert-or-reinterpret-between-namedtuple-and-svector/134600/6 "2025-12-17T04:09:23Z")

</div>

> [@matthias314](#):
>
> For some reason, one has to use `Tuple(v)` instead of `v`.

`reinterpret(T::DataType, A::AbstractArray)` tries to lazily reinterpret an array as an array of a different element type, rather than an instance of said type.

```julia-auto
julia> nt2 = reinterpret(typeof(nt), v); # can't be printed

julia> dump(nt2)
Base.ReinterpretArray{@NamedTuple{a::Float64, b::SVector{3, Float64}}, 1, Float64, SVector{4, Float64}, false}
  parent: SVector{4, Float64}
    data: NTuple{4, Float64}
      1: Float64 0.08744277749612084
      2: Float64 1.0
      3: Float64 2.0
      4: Float64 3.0
  readable: Bool true
  writable: Bool true

julia> eltype(nt2)
@NamedTuple{a::Float64, b::SVector{3, Float64}}

```

If we try to index it though, at some point it tries to convert the reinterpreted axes `1:1` to the type of the parent `SVector`’s axes `SOneTo{4}`, which is only compatible with `1:4`. Not really sure why that convert happens, ~~maybe for~~ does not allow automatic offset indices.

---

<div class="post-metadata">

**Author:** ![cortner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cortner/32/204_2.png) [@cortner](https://discourse.julialang.org/u/cortner)\
**Post date:** [December 17, 2025, 7:12pm UTC](https://discourse.julialang.org/t/convert-or-reinterpret-between-namedtuple-and-svector/134600/7 "2025-12-17T19:12:38Z")

</div>

Thanks for explaining, makes sense about SVector being an AbstractArray hence behaves differently.

But if I understand correctly, then `reinterpret` acting on a bitstype is intended as I’m using it? E.g.

```julia
reinterpret(Int, one(Float64))
# 4607182418800017408

reinterpret(Int, zero(Float64))
# 0

```

also does exactly what I’d expect.

---

<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:** [December 17, 2025, 7:33pm UTC](https://discourse.julialang.org/t/convert-or-reinterpret-between-namedtuple-and-svector/134600/8 "2025-12-17T19:33:07Z")

</div>

It’s all `isbits` reinterpretation, it’s just designed to do so across elements of an input `AbstractArray`. If the `axes` glitch wasn’t there, indexing the only element of the reinterpreted array would’ve returned the desired `NamedTuple`. Of course, reinterpreting the same bits as a `Tuple` is just easier.
