How to save a structure instance (inside module) in JLD2, to load it later correctly?

What should I add in initilizeFile.jl to make readingFile.jl gives the type of Sim as Simulation not JLD2.ReconstructedTypes.var"##Main.readApp.Simulation#292"(2.0, 4.0) with warning?
initilizeFile.jl is:

module readApp
using JLD2
Base.@kwdef mutable struct Simulation 
    dt::Float64 = 1e-6
    tmax::Float64 = 32*1e-3
end
function appFunction()
Sim = Simulation(2,4);
save("$(@__DIR__)/filename.jld2", "Sim", Sim)
end
appFunction();
end

readingFile.jl

using JLD2
Base.@kwdef mutable struct Simulation 
    dt::Float64 = 1e-6
    tmax::Float64 = 32*1e-3
end
Sim = load("$(@__DIR__)/filename.jld2", "Sim");
#Now I have warning
┌ Warning: type Main.readApp.Simulation does not exist in workspace; reconstructing
└ @ JLD2 C:\Users\amroa\.julia\packages\JLD2\k9Gt0\src\data\reconstructing_datatypes.jl:461
julia> typeof(Sim)
JLD2.ReconstructedTypes.var"##Main.readApp.Simulation#292"(2.0, 4.0)
# I need to remove the warning and to make typeof(Sim) gives Simulation as below
julia> typeof(Sim)
Simulation

Perhaps you need to using .readApp:

julia> module readApp
              using JLD2
              Base.@kwdef mutable struct Simulation
              dt::Float64 = 1e-6
              tmax::Float64 = 32*1e-3
              end
              function appFunction()
              Sim = Simulation(6,7);
              save("$(@__DIR__)/filename.jld2", "Sim", Sim)
              end
              appFunction();
       end
Main.readApp

julia> using JLD2, .readApp

julia> Sim = load("$(@__DIR__)/filename.jld2", "Sim")
Main.readApp.Simulation(6.0, 7.0)

Above code snippet is a single new REPL session.
Does this help?

1 Like

I don’t have much to say about it, except that I don’t understand

using base

It should be

using JLD2

I guess. With that it works for me.

I am sorry, I have corrected the type of using base to using JLD2 and rephrased my issue above.

It’s better not to edit the former posts, because the thread becomes hard to understand for people coming later back to the discussion. Answers start to make no sense anymore.

To your question, two ideas I have about this.
As already said, first idea, you can just use

using readApp

in readingFile.jl, but with that you will read in a Main.readApp.Simulation struct, which isn’t the same as a Main.Simulation struct. If this isn’t possible for you, which may be another issue, perhaps the real underlying issue of your issue here, the second idea, which comes into my mind is:

To bring readApp.Simulation into the Main scope by using eval(m::Module, x):

julia> module readApp
              using JLD2
              expr= :( Base.@kwdef mutable struct Simulation
                                dt::Float64
                                tmax::Float64
                            end )
              Base.eval( Main, expr )
              function appFunction()
                     Sim = Main.Simulation(2,4);
                     save("$(@__DIR__)/filename.jld2", "Sim", Sim)
              end
              appFunction();
       end
Main.readApp

julia> using JLD2


julia> Base.@kwdef mutable struct Simulation
           dt::Float64 = 1e-6
           tmax::Float64 = 32*1e-3
       end
Simulation

julia> Sim = load("$(@__DIR__)/filename.jld2", "Sim")
Simulation(2.0, 4.0)

julia> typeof(Sim)
Simulation

I am not an expert with expressions, macros and eval, but my guess is, there is a good reason, why eval(m::Module, x) isn’t exported from Base, so there may be some unexpected side effects with this solution.

Perhaps we are talking about a X-Y-Problem?

And of course, having two times the same definition of struct Simulation at different locations is considered to be a code smell and error prone.

1 Like

A working answer should already be here:

also:

@Amro: please avoid double posting (at least add cross references) to reduce confusion and double work from people trying to help.

2 Likes

Triple posted? Really?

@JonasIsensee have a look: Reconstructing warning when dealing with Module?

Well , 3 people involved, at least, what I can do is spreading some likes…

With the github issue it was quadruple posted. Assuming that it is the same OP.

Thanks for this, it works. However, I am having several structures and I create instances from them based on several scenarios. So, can I play on the instance directly in readingFile.jl, such as:

module readApp
using JLD2
Base.@kwdef mutable struct Simulation
  dt::Float64
  tmax::Float64
end
function appFunction()
Sim = Simulation(2,4);
expr= :( Sim )
Base.eval( Main, expr )
save("$(@__DIR__)/filename.jld2", "Sim", Sim)
end
appFunction();
end
ERROR: UndefVarError: Sim not defined

This would be:

julia> module readApp
                     using JLD2
                     Base.@kwdef mutable struct Simulation
                       dt::Float64
                       tmax::Float64
                     end
                     function appFunction()
                     expr= :( Sim = Main.readApp.Simulation(2,4) )
                                   Base.eval( Main, expr )
                     save("$(@__DIR__)/filename.jld2", "Sim", Main.Sim)
                     end
                     appFunction();
              end
Main.readApp

My recommendation is to not follow this path, unless you have read and understood every aspect of:
https://docs.julialang.org/en/v1.7/manual/variables-and-scoping/
and
https://docs.julialang.org/en/v1.7/manual/modules/

Thank you and I will follow your suggestion by re-reading the documentations.

Regarding my problem, my actual code includes building a vector of structure, as below.

module readApp
                     using JLD2
                     Base.@kwdef mutable struct Simulation
                       dt::Float64=2
                       tmax::Float64=3
                     end
                     function appFunction()
                      Sim = Simulation[]
                      push!(Sim, Simulation(2,4)) # number of pushes varies based on the run time
                      Base.eval( Main, expr )
                     save("$(@__DIR__)/filename.jld2", "Sim", Main.Sim)
                     end
                     appFunction();
              end

Is it possible to use expr= :( ) on the vector Sim eventually after it is pushed?