How to import a local module into another in different separate files

I wanted to know how to import a local module in a file into another in a different file.

so for instance, I have a situation like this:

#inside main.jl
include("M2.jl")
include("M1.jl")


function DoSomething(inputStringbody)
parsedJson = JSON.parse(inputStringbody)

ofTypeDataType = M2.makeDataType(parsedJson)

M1.useDataTypeToProcess(ofTypeDataType )

end

end
#inside file M1.jl
module M1
function useDataTypeToProcess( dataTypeParameter:: DataTypeModule.DataType1)
# do some processing with DataType
end

end
#inside file M2.jl
module M2

include("DataTypeModule.jl")
using Main.DataTypeModule

function makeDataType(someJson)

DataTypeModule.DataType1(someJson["name"], someJson["id"])

end 
end
#inside file DataTypeModule.jl
module DataTypeModule

struct DataType1

    name::String

     id::Int64

    function DataType1(

        name::String,

        id::Int64

        )

new(name,
id)


    end


end

If I run DoSomething(data), it breaks with a type mismatches saying:

MethodError: no method matching useDataTypeToProcess(::Main.M2.DataTypeModule.DataType1)

Closest candidates are:
seDataTypeToProcess(!Matched::Main.DataTypeModule.DataType1)

I could get around it by removing the include statement
include(“DataTypeModule.jl”)
and just use the using statement
using Main.DataTypeModule

But that breaks the tooling on the visual studio code. (Julia language support). Since it does not know where the DataTypeModule module is imported from.

So I was wondering how do you import a module so that it maintains the types and not break the useful tooling in the IDE.

Thank you

Could you have the line include("M2.jl") within module M1 ?
In M2 you may want to export DataType too.
Can you give that a try?

Someone else can probably give a more concrete answer (or point to the right documentation within Julia docs).

1 Like

Well it looks like when I include(“DataTypeModule.jl”) inside a module it copies everything in the included file into that module , thus creating a copy of the type but not the original type.

I am assuming this post is referring to the same issue
https://stackoverflow.com/a/48774908/5522453

1 Like

I think your struct should not be called DataType as that name/expression is used by Julia (Base?) itself

Could this work for you?
this works for me.

I note that include(....) is really the same as pasting code, thus you can amend the example below to include your files as long as the structure is maintained.

module M1
#export MyDataType

module M2
    export MyDataType

        module DataTypeModule
            export MyDataType
            struct MyDataType
                name::String
                id::Int64
                function MyDataType(name::String,id::Int64)
                    new(name,id)
                end#end function
            end#end struct
        end #module DataTypeModule

        function makeDataType(someJson)
            MyDataType(someJson["name"], someJson["id"])
        end 

    end #module M2 

     #using .M2 

    export useDataTypeToProcess 
    function useDataTypeToProcess(dataTypeParameter::M2.DataTypeModule.MyDataType)
        @show dataTypeParameter
    # do some processing with DataType
    end
    
end #module M1

ofTypeDataType = M1.M2.DataTypeModule.MyDataType("miha",22)

M1.useDataTypeToProcess(ofTypeDataType )
1 Like

I am sorry this was just an pseudo code.
I have edited the original question to reflect changes. the type name is something other than DataType

ok. please consider my answer above. Does that work for you?

Thank you for all the help.

That could work, but I was trying to get the VSCode tooling to recognize the import so that I get code completion and other tooling features. And the plugin still does not figure out the deep imports ie

M1.M2.DataTypeModule.MyDataType(“miha”,22)
it cannot traverse this chain to give me “go to definition”.

I am a web developer and we have great tooling and IDE support for all the frameworks and languages we use like typescript .net . and we love julia for how fast it is and has helped us to improve our product. but its frustrating coding without any of the IDE features we are used to.

ha ha I guess we are spoiled devs.

I have created an issue on their github page :

probably its a plugin issue may be.

I will update the post if I do find a solution or the situation changes.

Thanks

Perhaps the big picture question should be: do you really need all those modules? I understand that this is just a toy example, but it is unusual to see a lot of sub-modules unless code is rather large.

Assuming you need the modules, the logical approach would seem to define the types at the start (in a module or not). For example

module Main1

module MyTypes
    export DataType1
    struct DataType1
        x
    end
end
using .MyTypes

println(DataType1, " is known in Main1")

module M1
    import ..DataType1
    println(DataType1, " is known in M1")
end

end

I am not sure what you mean by some structure breaking VS Code. Do you mean that the linter shows unresolved references? That seems to be kind of a way of life in VS Code right now.

Sorry, posted my reply while you were typing your answer.

The code completion issue and lookup (F12) work (for me) when using a package that declares other packages as dependencies.

I never work outside of packages, so I have not tried whether it works when you have modules that live outside of packages.

Edit: Just tried it now. For me VS Code has no trouble finding where the definition of DataType1 lives, even if it’s in an included file. As expected, I guess.

Thank you! I forgot to mention we are a bit behind in terms of the Julia verison. We are on 1.0.3. Could be a potential cause.

I will try out the nested module approach you and @bernhard mentioned.

looks like that is the best practice to create modules.

thank you!

Also could you please let me know what the import …DataType1 does?

The import just brings DataType1 into scope. using ..MyTypes would have worked the same (for this example).

Just one piece of experience (or personal opinion, really). When I started out, I created lots of modules for one project. Then I found that this is a headache because there are usings all over the place and I constantly have to remember where each object is defined. So I got rid of all submodules.

Later, I realized that some parts of the projects really should not have to know anything about the rest (e.g. data preparation does not know anything about models). So I factored these out into packages (not sub-modules). That works well for me (keeping in mind that the project is pretty large; perhaps 10k LOC).

3 Likes