# Import struct without changing its "scope"

**URL:** https://discourse.julialang.org/t/import-struct-without-changing-its-scope/106529
**Category:** New to Julia
**Tags:** module, struct
**Created:** [November 21, 2023, 2:12pm UTC](https://discourse.julialang.org/t/import-struct-without-changing-its-scope/106529 "2023-11-21T14:12:59Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![Yue-Zhengyuan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yue-zhengyuan/32/220439_2.png) [@Yue-Zhengyuan](https://discourse.julialang.org/u/Yue-Zhengyuan)
#### Post date: [November 21, 2023, 2:12pm UTC](https://discourse.julialang.org/t/import-struct-without-changing-its-scope/106529/1 "2023-11-21T14:12:59Z")

</div>

I have problems on importing struct from other files. Suppose I have the file structure:

```julia
- Lattices.jl
- Hamiltonians.jl
- main.jl

```

`Lattices.jl` defines a struct called `Lattice`:

```julia
module Lattices
export Lattice

struct Lattice
    lx::Int64
    ly::Int64
end
end

```

`Hamiltonians.jl` defines `Hamiltonian` on a `Lattice`:

```julia
module Hamiltonians
export Hamiltonian

include("Lattices.jl")
using .Lattices

struct Hamiltonian
    lat::Lattice
    coeffs::Vector{Float64}
end
end

```

`main.jl` tries to create a `Hamiltonian`:

```julia
include("Lattices.jl")
include("Hamiltonians.jl")
using .Lattices
using .Hamiltonians

a = Lattice(16, 16)
ham = Hamiltonian(a, [1.0, 0.0])
display(ham)

```

However, I get the error

```julia
ERROR: LoadError: MethodError: Cannot `convert` an object of type Lattice to an object of type Main.Hamiltonians.Lattices.Lattice

```

So the problem is that when I import `Lattice` into the `Hamiltonians` module, its “scope” is also changed (sorry if I am not using the correct terminology; I come from Python so I have never encountered such behavior before). It is no longer regarded as the same `Lattice` from `Lattices.jl`. How do I tell Julia that different `Lattice`’s are the same thing?

---

<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: [November 21, 2023, 2:22pm UTC](https://discourse.julialang.org/t/import-struct-without-changing-its-scope/106529/2 "2023-11-21T14:22:05Z")

</div>

You should not `include("Lattices.jl")` inside “Hamiltonians”, because `include` is like copying-and-pasting the code there. That means that you are defining a completely independent `Lattices` module inside `Hamiltonians`.

What you want there is to use:

```julia
module Hamiltonians
export Hamiltonian

using ..Lattices # two dots
...

```

to load the module you defined before.

(the takeaway is: never `include` the same file twice).

---

<div class="post-metadata">

### Author: ![Yue-Zhengyuan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yue-zhengyuan/32/220439_2.png) [@Yue-Zhengyuan](https://discourse.julialang.org/u/Yue-Zhengyuan)
#### Post date: [November 21, 2023, 2:30pm UTC](https://discourse.julialang.org/t/import-struct-without-changing-its-scope/106529/3 "2023-11-21T14:30:15Z")

</div>

Thanks! Actually I never understand the dots in front of the module names. Could you please further explain? In addition, if `Lattices.jl` is in a folder `lattices/Lattices.jl`, the two-dot import will not work; how to deal with this case?

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [November 21, 2023, 2:38pm UTC](https://discourse.julialang.org/t/import-struct-without-changing-its-scope/106529/4 "2023-11-21T14:38:16Z")

</div>

The dots indicate relative module paths. When you import a package, you don’t have dots because packages are stored distantly; the lack of dots informs the import statement to look elsewhere. In this case, you are `include`ing a module directly into your module tree (`Main` containing modules that can contain other modules). To share names among the modules, you do dotted imports, the dots helping the import statement walk along the tree. So that’s why you don’t want to `include` twice, you’re evaluating a copy, a separate branch so to speak.

tbh, the dots still gets me with off-by-one errors, but hopefully this contrived example helps:

```julia
julia> module Foo
         module Bar0 end
         module Bar1
           module Bar2 end
           using ...Foo # Bar1 -> Foo -> Main.Foo
           using ..Foo # Bar1 -> Foo.Foo (watch out, modules contain own name)
           using ..Bar0 # Bar1 -> Foo.Bar0
           using .Bar2 # Bar1.Bar2
         end 
       end;

```

One dot is a starting point, it just means you look in the global scope that the import statement is in. With each additional dot, you go up a global scope to look. With enough dots you reach `Main`, and more dots won’t go anywhere.

The dots are necessary. You can’t qualify the name of the searched scope like `relativeimport Foo.Bar0` because two separate modules can share the name `Foo` in different branches of the module tree. If it helps you look up a file faster, you could just comment the name like the above and use the dots to tell synonyms apart sometimes; I personally don’t nest modules deeply so the walk isn’t far. The `Bar0` part on the other hand must be named to select one out of possibly many modules in the searched scope.

---

<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: [November 21, 2023, 2:47pm UTC](https://discourse.julialang.org/t/import-struct-without-changing-its-scope/106529/5 "2023-11-21T14:47:38Z")

</div>

> [@Yue-Zhengyuan](#):
>
> In addition, if `Lattices.jl` is in a folder `lattices/Lattices.jl`

The `include` command will change, but not the `using ..Lattices` (in that case).

That said, the most common approach is to just have one “big module”, lets say, called “MyQuantumPackage”, and just include the source of the sub-functionalities in that module, without splitting them into different modules each (which will make your like harder). Something like:

```julia-auto
module MyQuantumPackage
      include("lattices/Lattices.jl")
      include("Hamiltonian.jl")
end

```

where `Lattices.jl` is just:

```julia-auto
export Lattice

struct Lattice
    lx::Int64
    ly::Int64
end

```

(without the module), and the same for `Hamiltonian`, such that you don’t need to import names from other modules all the time within your package.

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [November 21, 2023, 3:02pm UTC](https://discourse.julialang.org/t/import-struct-without-changing-its-scope/106529/6 "2023-11-21T15:02:24Z")

</div>

In other words, split into modules if you need separate namespaces that share select names via imports. If you don’t need such encapsulation, it’s easier to work in 1 namespace, and `include` can evaluate multiple source files into it, which helps prevent a big namespace from making too big a file.

---

<div class="post-metadata">

### Author: ![Yue-Zhengyuan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yue-zhengyuan/32/220439_2.png) [@Yue-Zhengyuan](https://discourse.julialang.org/u/Yue-Zhengyuan)
#### Post date: [November 22, 2023, 3:56am UTC](https://discourse.julialang.org/t/import-struct-without-changing-its-scope/106529/7 "2023-11-22T03:56:58Z")

</div>

@Benny in your example, what is the difference between Main.Foo and Foo?

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [November 22, 2023, 4:50am UTC](https://discourse.julialang.org/t/import-struct-without-changing-its-scope/106529/8 "2023-11-22T04:50:21Z")

</div>

`Main` and `Foo` are names of 2 modules. Modules contain their own names by default and the names of nested modules, so `Foo.Foo` and `Main.Foo` access the same module. I was warning you of that because it might be confusing why `using ..Foo` and `using ...Foo` both work; you’re just searching the name `Foo` in different modules.

I recommend avoiding `Foo.Foo` so the same number of dots reach modules on the same level; `Foo` isn’t on the level of `Bar0` or any other module it may contain. It’ll also cover the pathological cases where a module’s own contained name is reassigned to another module:

```julia
julia> module Foo
         export x
         x = "outer"
         module Foo # don't repeat names in practice
           export x
           x = :inner
         end
         module Bar
           using ..Foo # Bar -> Foo.Foo
         end
       end
WARNING: replacing module Foo.
Main.Foo

julia> Foo, Foo.Foo
(Main.Foo, Main.Foo.Foo)

julia> Foo.Bar.x
:inner

```
