# Order matters in the conflicts with imported names

**URL:** <https://discourse.julialang.org/t/order-matters-in-the-conflicts-with-imported-names/59628>\
**Category:** General Usage\
**Created:** [April 19, 2021, 11:43pm UTC](https://discourse.julialang.org/t/order-matters-in-the-conflicts-with-imported-names/59628 "2021-04-19T23:43:41Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![heliosdrm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/heliosdrm/32/3851_2.png) [@heliosdrm](https://discourse.julialang.org/u/heliosdrm)\
**Post date:** [April 19, 2021, 11:43pm UTC](https://discourse.julialang.org/t/order-matters-in-the-conflicts-with-imported-names/59628/1 "2021-04-19T23:43:41Z")

</div>

I have been struggling to understand the nuances of what happens when there are conflicts with names imported from other modules.

I eventually found by myself a consistent explanation for `import Foo: bar`. If I’m not mistaken, in practice that’s the same as attempting to bind the content of `Foo.bar` to `Main.bar` (replace `Main` with the module into which you are importing): if `Main.bar` already exists, the import is ignored with a warning; and if the name is available, it’s taken. That’s all.

However, with `using` things become complicated, and the results depend a lot on the order in which things are done. It is as if `using` makes some kind of “lazy import” with the exported names. So, if I load two packages that export shared names, I get this well-known warning when I first try to use the offending name:

```julia-repl
julia> module M1
           export foo
           foo() = 1
       end
Main.M1

julia> module M2
           export foo
           foo() = 2
       end
Main.M2

julia> using .M1, .M2

julia> foo()
WARNING: both M2 and M1 export "foo"; uses of it in module Main must be qualified

```

But if I load one of the modules and use the exported name _before loading the other_, the first takes the place in `Main`:

```julia-repl
julia> module M1
           export foo
           foo() = 1
       end
Main.M1

julia> module M2
           export foo
           foo() = 2
       end
Main.M2

julia> using .M1

julia> foo()
1

julia> using .M2
WARNING: using M2.foo in module Main conflicts with an existing identifier.

julia> foo === M1.foo
true

```

That sort of “lazy import” produces other inconsistencies in certain corner cases. For instance:

If I define something with the exported names in `Main` after `using` the module, but before calling that name for the first time, it’s as if I had defined it before `using` (there is a conflict and the import does not happen), but the warning is missed:

```julia-repl
julia> module M1
           foo() = 1
       end
Main.M1

julia> using .M1

julia> foo() = 2 # No warning
foo (generic function with 1 method)

julia> foo()
2

julia> M1.foo()
1

```

Besides, if the name is successfully imported, although functions are not available for method extension with just their “raw” names, I can extend them by prefixing not only the name of the original module, but also `Main` (or whatever module I’m in):

```julia-repl
julia> module M1
           export foo
           foo() = 1
       end
Main.M1

julia> using .M1

julia> foo()
1

julia> foo(x) = 2 # I knew that this is not allowed
ERROR: error in method definition: function M1.foo must be explicitly imported to be extended
Stacktrace:
 [1] top-level scope at none:0
 [2] top-level scope at REPL[5]:1

julia> Main.foo(x) = 2 # instead of orthodox M1.foo

julia> M1.foo("hi") # This is very confusing, isn't it?
2

julia> Main.foo === M1.foo
true

```

I found these apparent inconsistencies after having read the [documentation about modules](https://docs.julialang.org/en/v1/manual/modules/#modules), and honestly in my eyes they looked as a somewhat buggy behavior. Upon a second read (after having experimented with this), I realized that the documentation is accurate, and the observed results are consistent. For what is worth, these are the key paragraphs that I had failed to understand:

> [@](#):
>
> When a global variable is encountered that has no definition in the current module, the system will search for it among variables exported by `ModuleName` and use it if it is found there. This means that all uses of that global within the current module will resolve to the definition of that variable in `ModuleName` [_this contains the idea that I was calling “lazy import”_].

> [@](#):
>
> Once a variable is made visible via `using` or `import` , a module may not create its own variable with the same name. Imported variables are read-only; assigning to a global variable always affects a variable owned by the current module, or else raises an error. [_This is where it is clarified that the imported names are not just “visible” in the current module, but also bound to it._]

My question is whether other people think that this is clear enough --so my confusion was a personal failure to understand that information–, or it might be worth to emphasize or rephrase it to make it clearer. Maybe a section explaining conflicts caused by imports?

---

<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:** [April 20, 2021, 12:01am UTC](https://discourse.julialang.org/t/order-matters-in-the-conflicts-with-imported-names/59628/2 "2021-04-20T00:01:58Z")

</div>

In my humble opinion, you raise awareness for different behaviours that might be confusing, but I don’t find them inconsistent. The only one thing that was surprising to me was the possibility of overloading the module function with the `Main` binding.

> [@heliosdrm](#):
>
> `julia> Main.foo(x) = 2 # instead of orthodox M1.foo`

That is not inconsistent (because the functions are the same), but certainly very confusing. Hopefully nobody will ever do that 😃

Describing those behaviours in words is so hard that I don’t know if anyone would benefit from a rewrite of the docs except if the docs contained the examples themselves.

---

<div class="post-metadata">

**Author:** ![heliosdrm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/heliosdrm/32/3851_2.png) [@heliosdrm](https://discourse.julialang.org/u/heliosdrm)\
**Post date:** [April 20, 2021, 2:37pm UTC](https://discourse.julialang.org/t/order-matters-in-the-conflicts-with-imported-names/59628/3 "2021-04-20T14:37:43Z")

</div>

Yes, after re-reading I found that the documentation is accurate, just that I had a wrong understanding of what it tells. To be precise, my incorrect preconceived ideas were:

1. That `using .M1` would create bindings in the current module for the variables exported by `M1` immediately, not later, when those variables are “read” for the first time.

2. That if `foo` has been made visible in `Main` by `using .M1`, then the definition of the method `Main.foo(x) = 2` would either:

I know that all that is wrong; the docs don’t mean that. But I was not sure if now I understand it because I read it more carefully, or because after some experimentation and unexpected results I can make the right connections with the written statements. If my initial failure to understand it right is accidental and personal, we can leave it as it is. If others might arrive at similar wrong assumptions as I did, perhaps some clarifying examples or explanations would be suitable.
