Structs in Modules

So I have two modules that I wrote, SparseRowEchelon.jl and SparseBasis.jl.
SparseRowEchelon includes a struct that is also used in SparseBasis, and this causes a problem when my main file tries to call a function in SparseBasis.

SparseRowEchelon.jl looks like this:

module SparseRowEchelon

export foo, SparseRREF

using SparseArrays

struct SparseRREF
    T::Vector{SparseVector}
    isPiv::BitArray
end

# some functions, including foo()

end

and SparseBasis.jl looks like this

module SparseBasis

using SparseArrays
include("SparseRowEchelon.jl")
using .SparseRowEchelon

export get_spbasis

function get_spbasis(sparse_rref::SparseRREF)
    # blah blah blah
end

end

So SparseBasis is using a struct that I defined in SparseRowEchelon.

The problem is when I go to use these modules in another file, called modeling.jl.

include("SparseRowEchelon.jl")
using .SparseRowEchelon

my_sparce_rref = foo() # does a thing that returns type `SparseRREF`

include("SparseBasis.jl")
using .SparseBasis

get_spbasis(my_sparce_rref)

This returns the error that they cannot find method get_spbasis.

MethodError: no method matching get_spbasis(::SparseRREF)
Closest candidates are:
get_spbasis(!Matched::Main.SparseBasis.SparseRowEchelon.SparseRREF) at [path to SparseBasis.jl]:10

That is the method I want it to use, but why doesn’t it want to use it? And how can I fix it?

Thanks!

You include the file "SparseRowEchelon.jl" twice; once inside SparseBasis and once in Main (i.e. the REPL). This means that you define the module and structs in there twice, so SparseRowEchelon.SparseRREF is NOT the same struct as SparseBasis.SparseRowEchelon.SparseRREF are different structs. get_spbasis is defined for SparseBasis.SparseRowEchelon.SparseRREF and not SparseRowEchelon.SparseRREF and hence you get a method error.

You should only include the same file one time, generally speaking. Then you have to decide if you want to do it inside your other module, or only at the outside as a separate module.

1 Like

So if the struct is being used in both SparseBasis and SparseRowEchelon and also in my main file, what would you say is the best way of handling this?

You have to decide where you define it, and then use that same definition at all the places. I would just have everything in the same module, e.g.

module SparseBasis
...

include("SparseRowEchelon.jl")
using .SparseRowEchelon

end

and then when you use it in the REPL you just include that file.

1 Like

That works. Thanks! :smile:

(Also needed to add SparseRowEchelon’s exports to SparseBasis.)