# Change a struct in place

**URL:** <https://discourse.julialang.org/t/change-a-struct-in-place/63914>\
**Category:** General Usage\
**Tags:** hack\
**Created:** [July 1, 2021, 7:42pm UTC](https://discourse.julialang.org/t/change-a-struct-in-place/63914 "2021-07-01T19:42:09Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)\
**Post date:** [July 1, 2021, 7:42pm UTC](https://discourse.julialang.org/t/change-a-struct-in-place/63914/1 "2021-07-01T19:42:09Z")

</div>

I made a struct with `Float32`

```julia
julia> struct Foo 
       x::Float32
       end

julia> foo = Foo(1)
Foo(1.0f0)

```

But now I realized `Float32` isn’t big enough and I want `Float64`, and I want the change to propagate to the instantiated `foo` object (not just creating a bigger `NewFoo`). I believe this isn’t supported.

```julia
julia> Foo.types
svec(Float32)

julia> typeof(Foo.types)
Core.SimpleVector

julia> ismutable(Core.SimpleVector)
true

julia> Foo.types[1]
Float32

julia> Foo.types[1] = Float64
ERROR: MethodError: no method matching setindex!(::Core.SimpleVector, ::Type{Float64}, ::Int64)
Stacktrace:
 [1] top-level scope
   @ REPL[10]:1 

```

Is there an (unsupported, hacky) way to do it anyway?

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [July 1, 2021, 7:46pm UTC](https://discourse.julialang.org/t/change-a-struct-in-place/63914/2 "2021-07-01T19:46:28Z")

</div>

```julia
mutable struct Foo
    x::Float32
end

```

---

<div class="post-metadata">

**Author:** ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)\
**Post date:** [July 1, 2021, 7:51pm UTC](https://discourse.julialang.org/t/change-a-struct-in-place/63914/3 "2021-07-01T19:51:45Z")

</div>

I’m looking for something different that changes the type itself, rather than the values of the instances.

```julia
julia> mutable struct Foo
           x::Float32
       end

julia> Foo.types[1] = Float64
ERROR: MethodError: no method matching setindex!(::Core.SimpleVector, ::Type{Float64}, ::Int64)

```

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [July 1, 2021, 8:00pm UTC](https://discourse.julialang.org/t/change-a-struct-in-place/63914/4 "2021-07-01T20:00:30Z")

</div>

Ah sorry for not reading your question more closely.

No, I do not believe that is possible. Of course, you can always re-define the type entirely to allow for other types.

---

<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:** [July 1, 2021, 11:58pm UTC](https://discourse.julialang.org/t/change-a-struct-in-place/63914/5 "2021-07-01T23:58:21Z")

</div>

Or you could have defined a parametric type from the start:

```julia
struct Foo{T}
    x :: T
end

```

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [July 2, 2021, 6:13am UTC](https://discourse.julialang.org/t/change-a-struct-in-place/63914/6 "2021-07-02T06:13:14Z")

</div>

Not sure it is what you need, but just in case, check [this package](https://github.com/FedericoStra/RedefStructs.jl) by @FedericoStra

---

<div class="post-metadata">

**Author:** ![doit](https://avatars.discourse-cdn.com/v4/letter/d/9dc877/32.png) [@doit](https://discourse.julialang.org/u/doit)\
**Post date:** [July 2, 2021, 6:55am UTC](https://discourse.julialang.org/t/change-a-struct-in-place/63914/7 "2021-07-02T06:55:19Z")

</div>

![200](https://global.discourse-cdn.com/julialang/original/3X/f/7/f7b89d8a6f1419e89f42701ab3c0d062bfe265ac.gif)  
I mean because of parametric types.

---

<div class="post-metadata">

**Author:** ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)\
**Post date:** [July 2, 2021, 7:32am UTC](https://discourse.julialang.org/t/change-a-struct-in-place/63914/8 "2021-07-02T07:32:58Z")

</div>

Parametric types make multiple concrete types, not one type that can be changed in place. For example say I’ve made a struct, instantiated it, moved it around in my program. Now I want to add a new field to the type and to existing instances, in place.

---

<div class="post-metadata">

**Author:** ![Per](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/per/32/10387_2.png) [@Per](https://discourse.julialang.org/u/Per)\
**Post date:** [July 2, 2021, 7:52am UTC](https://discourse.julialang.org/t/change-a-struct-in-place/63914/9 "2021-07-02T07:52:36Z")

</div>

I don’t think there’s easy way to do this. Changing the definition of a type, would require finding every instance of that type (including in boxes and closures, etc) and also recompiling every method that uses it.

If you are just prototyping code, and don’t care that it runs a bit slower, you could do this:

```julia
struct Foo
    x::Any
end
foo = Foo(1)

Base.getproperty(v::Foo, s::Symbol) = Float32(getfield(v, s))
typeof(foo.x) # Float32

Base.getproperty(v::Foo, s::Symbol) = Float64(getfield(v, s))
typeof(foo.x) # Float64

```

This does not change what is actually stored in `foo`, but it does change what it _appears_ to be.

---

<div class="post-metadata">

**Author:** ![doit](https://avatars.discourse-cdn.com/v4/letter/d/9dc877/32.png) [@doit](https://discourse.julialang.org/u/doit)\
**Post date:** [July 2, 2021, 9:12am UTC](https://discourse.julialang.org/t/change-a-struct-in-place/63914/10 "2021-07-02T09:12:59Z")

</div>

Sorry, my message was meant as a direct reply to @rafael.guerra because to me it seems that package kind of mimics parametric types, or rather when you define a struct in a manner that allows any field type so that you can dispatch on the parametric type.

I’m unsure that the solution proposed by @Per actually solves your problem though:

> But now I realized `Float32` isn’t big enough and I want `Float64`

because you wouldn’t be able to change the underlying concrete type of the field, just how it appears “outside” (as he mentions himself).

You should really try the route of parametric types (like @Henrique_Becker said) as in

```julia
mutable struct Foo{T}
    x::T
end

```

And then simply recast your data whenever necessary:

```julia
a = Foo(Float32(1))

# later
a = Foo(Float64(a.x))

```

You can even write convenience functions for that and if you need to recast an array of your data, use list comprehensions, etc.

```julia
Foo(T::Type,foo::Foo) = Foo(T(foo.x))

# Float32
r = Foo.(Float32.(rand(3)))

# Float64
r = Foo.(Float64,r)

```

There are probably better ways to do this still.

Edit:  
You should probably make the struct mutable because it seems to me that you want to change the contents of the field after the fact.

---

<div class="post-metadata">

**Author:** ![doit](https://avatars.discourse-cdn.com/v4/letter/d/9dc877/32.png) [@doit](https://discourse.julialang.org/u/doit)\
**Post date:** [July 2, 2021, 9:19am UTC](https://discourse.julialang.org/t/change-a-struct-in-place/63914/11 "2021-07-02T09:19:04Z")

</div>

Structs in Julia are not meant to be used like structs in Matlab for example. Structs are meant to represent user-definable types on which you want to dispatch to do very specific things. That’s why you can’t change their definition afterwards but you can “always” dispatch on parametric types to do more specific things.

If you want a container that has a mutable number of fields, you should use Dicts probably, shouldn’t you?

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [July 2, 2021, 9:39am UTC](https://discourse.julialang.org/t/change-a-struct-in-place/63914/12 "2021-07-02T09:39:08Z")

</div>

For Julia type system beginners, would you mind commenting the problem with code below? Thank you.

```julia
using RedefStructs

@redef struct Foo
    x::Float32
end

y = Foo(1.0).x # 1.0f0
julia> typeof(y)
Float32

@redef struct Foo
    x::Float64
end
y = Foo(1.0).x
julia> typeof(y)
Float64

```

---

<div class="post-metadata">

**Author:** ![Per](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/per/32/10387_2.png) [@Per](https://discourse.julialang.org/u/Per)\
**Post date:** [July 2, 2021, 9:43am UTC](https://discourse.julialang.org/t/change-a-struct-in-place/63914/13 "2021-07-02T09:43:32Z")

</div>

I think this might an [XY problem](https://en.wikipedia.org/wiki/XY_problem). Instead of asking “how can I change the definition of a struct in Julia?”, it might be more appropriate to ask “what Julia construct can be used in place of the re-definable structs of [some other language]?” to which the answer is:

> [@doit](#):
>
> you should use Dicts probably

This would be a lot easier than the solution that I gave above, and not have any worse performance.

---

<div class="post-metadata">

**Author:** ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)\
**Post date:** [July 2, 2021, 9:47am UTC](https://discourse.julialang.org/t/change-a-struct-in-place/63914/14 "2021-07-02T09:47:22Z")

</div>

> [@Per](#):
>
> > [@doit](#):
> >
> > you should use Dicts probably
> 
> This would be a lot easier than the solution that I gave above, and not have any worse performance.

I think dicts have a different layout than structs and different performance characteristics.

The point of this question is about a long-running interactive system where I define a struct as normal, and then change the application without restarting. That is, using struct as intended, and then evolving the application – just without restarting. Consider large interactive Lisp systems to compare.

I’m not a CLOS person but I believe it has this feature.

[http://www.lispworks.com/documentation/HyperSpec/Body/f\_mk\_i\_1.htm#make-instances-obsolete](http://www.lispworks.com/documentation/HyperSpec/Body/f_mk_i_1.htm#make-instances-obsolete)

[http://www.lispworks.com/documentation/HyperSpec/Body/f\_upda\_1.htm](http://www.lispworks.com/documentation/HyperSpec/Body/f_upda_1.htm)

---

<div class="post-metadata">

**Author:** ![doit](https://avatars.discourse-cdn.com/v4/letter/d/9dc877/32.png) [@doit](https://discourse.julialang.org/u/doit)\
**Post date:** [July 2, 2021, 9:48am UTC](https://discourse.julialang.org/t/change-a-struct-in-place/63914/15 "2021-07-02T09:48:46Z")

</div>

I think for this very specific example RedefStructs.jl is overkill because you can alleviate the problem of the internally strictly defined type of field `x` via the use of parametric types.  
If I understand RedefStructs.jl correctly (and please, someone correct me if I am wrong), it defines new surrogate structs with the correct type signature with a new name anyway and simply reassigns the name so to you it appears as if you have redefined the struct.  
Under the hood what it is doing is equivalent to you writing

```julia
struct FooA
    x::Float32
end

struct FooB
    x::Float64
end

```

But it additionally updates the name table so that `Foo` refers to `FooB` instead of `FooA`. In this specific case though, you can use parametric types and evade the problem of defining multiple instances of `Foo`.

Of course, changing the fieldnames or the number of fields in a struct cannot be done after the fact. To reiterate, though, that’s not what structs are meant to do.

---

<div class="post-metadata">

**Author:** ![doit](https://avatars.discourse-cdn.com/v4/letter/d/9dc877/32.png) [@doit](https://discourse.julialang.org/u/doit)\
**Post date:** [July 2, 2021, 9:53am UTC](https://discourse.julialang.org/t/change-a-struct-in-place/63914/16 "2021-07-02T09:53:23Z")

</div>

> [@jzr](#):
>
> I think dicts have a different layout than structs and different performance characteristics.
> 
> The point of this question is about a long-running interactive system where I define a struct as normal, and then change the application without restarting. That is, using struct as intended, and then evolving the application – just without restarting. Consider large interactive Lisp systems to compare.

If you want to change the application of your programm while it is running, it makes more sense to have defined an appropriate new type and then convert your old type into the new type by, for example, filling fields appropriately.  
That way you can still effectively use dispatch.

Edit: Of course, if you very frequently “evolve” your program that might become ineffictive at some point, I guess 🤷‍♂️

---

<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:** [July 2, 2021, 10:12am UTC](https://discourse.julialang.org/t/change-a-struct-in-place/63914/17 "2021-07-02T10:12:23Z")

</div>

> [@jzr](#):
>
> ```julia
> mutable struct Foo 
> x::Union{Float32,Float64}
> end
> 
> ```

Of course this is horrible for performance, but I don’t think take “in place” can mean anything except that a pointer is kept if the type of the field changes. If you need to add more fields of different types, use vectors of union types.

---

<div class="post-metadata">

**Author:** ![Per](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/per/32/10387_2.png) [@Per](https://discourse.julialang.org/u/Per)\
**Post date:** [July 2, 2021, 11:01am UTC](https://discourse.julialang.org/t/change-a-struct-in-place/63914/18 "2021-07-02T11:01:03Z")

</div>

> [@jzr](#):
>
> The point of this question is about a long-running interactive system

What people often use for this is some kind of database backend. That also makes it easier to recover from accidents and power outages.

---

<div class="post-metadata">

**Author:** ![doit](https://avatars.discourse-cdn.com/v4/letter/d/9dc877/32.png) [@doit](https://discourse.julialang.org/u/doit)\
**Post date:** [July 2, 2021, 11:06am UTC](https://discourse.julialang.org/t/change-a-struct-in-place/63914/19 "2021-07-02T11:06:03Z")

</div>

I agree and just want to _heavily_ emphasize again that you _really_ shouldn’t define types like this for performance reasons.  
In case it’s necessary, you _can_ restrict parametric types:

```julia
mutable struct Foo{T<:AbstractFloat}
    x::T
end

Foo(3) # ERROR: MethodError: no method matching Foo(::Int64)

Foo("string") # ERROR: MethodError: no method matching Foo(::String)

Foo(3.0) # Foo{Float64}(3.0)

```

---

<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:** [July 2, 2021, 11:08am UTC](https://discourse.julialang.org/t/change-a-struct-in-place/63914/20 "2021-07-02T11:08:38Z")

</div>

Sure, but in that case you cannot change the type of an instance of the object to another type.

But, again, nobody should do that anyway.

[Next page](https://discourse.julialang.org/t/change-a-struct-in-place/63914.md?page=2)
