Objects whose structure can be redefined

One thing I’ve noticed about Julia that is a little frustrating is that if I define an object like this:

struct paramObj
   g::Float64
   l::Float64
end

params = paramObj(9.81, 1.0);

and then import a file that contains this:

struct paramObj
   sigma::Float64
   beta::Float64
   rho::Float64
end

params = paramObj(28.0, 8/3, 10.0); 

I’ll get an error essentially saying that paramObj is a constant and hence cannot be redefined (specifically invalid redefinition of constant paramObj). Is there a way of creating objects in Julia such that redefining the object structure doesn’t give you an error?

1 Like

Yes. You need to have the two object in different namespaces, for example in different modules. For example, check FASTX.jl, which contain two different objects called Record in distinct submodules. These can then be disambiguated by their module name.
You can’t have two different objects with the same name in the same namespace. If you did, how would it be possible to distinguish between the two?

1 Like

I was hoping that it’d be like redefining a function, or a variable, where the new definition leads to the old definition no longer existing in memory. I should clarify the context here, I’m not talking about a package I’m building, I’m talking about JL files I’m loading through include("filename.jl"), so I’m not sure using different modules will work. Feel free to correct me if I’m wrong.

The problem with redefining structs is that all existing code using that struct would have to be recompiled, as the new number of fields necessarily means a different memory layout as well. Doing this on-the-fly would mean potentially having to recompile the very code you’re running right now while it’s running, and since that’s not allowed, struct redefinition at runtime isn’t either.

If you have the need to explore how your struct should look, try prototyping usind NamedTuples combined with Revise.jl, and only settling on a struct once you know how to best organize youre code.

If you could tell us more about what you’re trying to achieve, we may be able to suggest a more julian approach. Redefining existing structs feels very much like a workflow used in e.g. python (which is interpreted and not compiled, and thus doesn’t suffer from the above problem since everything is a dynamic lookup anyway).

3 Likes

This other question of mine shows how I’m using paramObj. In essence, I’m using it to store parameter values that I hand to an ODE-solving function that then passes it to a function representing the right-hand side of the system of first-order ordinary differential equations being integrated. I know I could use an array instead, it’s just it’s more convenient using an object where you can extract the values using the dot notation, as otherwise you need to remember the order in which you entered the parameters into the array.

That’s why I suggested using NamedTuples instead:

julia> f = (a=4,b="hello!")
(a = 4, b = "hello!")

julia> f.a
4

julia> f.b
"hello!"
5 Likes

Ah, my apologies I will admit I’m still fairly new to the language, but that sounds like a great idea, thanks!

1 Like

No worries! :slight_smile:

Once you know how exactly you want to pass around your data, you can switch the NamedTuple approach to the finalized struct version and you might even get a performance boost.

If you haven’t done so yet, I suggest giving the manual a read, especially the section about noteworthy differences from other languages.

Some variant of it will hopefully work in the long run though, see

https://github.com/timholy/Revise.jl/issues/18